package com.xueyi.workflow.service.impl;

import com.xueyi.common.core.web.page.TableDataInfo;
import com.xueyi.common.security.utils.SecurityUtils;
import org.apache.commons.lang3.StringUtils;
import com.xueyi.workflow.domain.dto.WfProcessTaskDto;
import com.xueyi.workflow.domain.dto.SubmitApprovalRequest;
import com.xueyi.workflow.domain.dto.SubmitApprovalRequest.NextNodeConfig;
import com.xueyi.workflow.domain.dto.SubmitApprovalRequest.HandlerInfo;
import com.xueyi.workflow.domain.dto.WfProcessApprovalDto;
import com.xueyi.workflow.domain.query.WfProcessApprovalQuery;
import com.xueyi.workflow.domain.query.WfProcessTaskQuery;
import com.xueyi.workflow.domain.query.WfProcessVersionQuery;
import com.xueyi.workflow.domain.dto.WfProcessVersionDto;
import com.xueyi.workflow.manager.WfProcessVersionManager;
import com.xueyi.workflow.service.IWfProcessTaskService;
import com.xueyi.workflow.service.IWfProcessApprovalService;
import com.xueyi.workflow.service.IWfProcessInstanceService;
import com.xueyi.workflow.service.IWorkflowUserService;
import com.xueyi.workflow.event.ProcessCompletedEvent;
import com.xueyi.workflow.event.ProcessStatusChangedEvent;
import com.xueyi.workflow.manager.ProcessStatusManager;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Arrays;
import java.util.stream.Collectors;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.bpmn.model.SequenceFlow;
import org.flowable.bpmn.model.UserTask;
import org.flowable.bpmn.model.ExclusiveGateway;
import org.flowable.bpmn.model.ParallelGateway;
import org.flowable.bpmn.model.InclusiveGateway;
import org.flowable.bpmn.model.EndEvent;
import org.flowable.bpmn.model.ServiceTask;
import com.xueyi.workflow.domain.vo.NextNodeInfo;
import java.util.Collection;
import org.flowable.bpmn.model.StartEvent;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.Gateway;
import org.flowable.bpmn.model.ScriptTask;
import com.xueyi.workflow.domain.vo.GatewayBranchInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashSet;
import java.util.Date;
import org.flowable.identitylink.api.IdentityLink;
import com.xueyi.workflow.service.IWfProcessVersionService;

/**
 * 流程任务Service业务层处理
 *
 * @author xueyi
 * @date 2024-07-03
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class WfProcessTaskServiceImpl implements IWfProcessTaskService {

    @Autowired
    private TaskService taskService;
    
    @Autowired
    private HistoryService historyService;
    
    @Autowired
    private RepositoryService repositoryService;
    
    @Autowired
    private RuntimeService runtimeService;
    
    @Autowired
    private WfProcessVersionManager wfProcessVersionManager;
    
    @Autowired
    private IWfProcessApprovalService wfProcessApprovalService;

    @Autowired
    private IWfProcessInstanceService wfProcessInstanceService;

    @Autowired
    private IWorkflowUserService workflowUserService;
    
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;
    
    @Autowired
    private ProcessStatusManager processStatusManager;

    @Autowired
    private IWfProcessVersionService wfProcessVersionService;

    /**
     * 查询我的任务分页列表
     */
    @Override
    public TableDataInfo<WfProcessTaskDto> getMyTasks(WfProcessTaskQuery query) {
        try {
            // 调试：检查 Flowable 流程定义表
            log.info("=== 开始查询我的任务 ===");
            long processDefinitionCount = repositoryService.createProcessDefinitionQuery().count();
            log.info("Flowable 流程定义总数: {}", processDefinitionCount);
            
            if (processDefinitionCount > 0) {
                List<ProcessDefinition> allDefinitions = repositoryService.createProcessDefinitionQuery()
                    .orderByProcessDefinitionKey()
                    .asc()
                    .list();
                log.info("所有流程定义:");
                for (ProcessDefinition def : allDefinitions) {
                    log.info("  - Key: {}, Name: {}, ID: {}", 
                            def.getKey(), def.getName(), def.getId());
                }
            }
            
            // 从Flowable查询任务
            List<Task> tasks = new ArrayList<>();

            // 获取当前用户ID
            String currentUserId = getCurrentUserId();
            log.info("查询用户 {} 的待办任务", currentUserId);

            // 调试：查询所有任务
            List<Task> allTasks = taskService.createTaskQuery().list();
            log.info("系统中总共有 {} 个任务", allTasks.size());
            for (Task task : allTasks) {
                log.info("任务: ID={}, Name={}, Assignee={}, ProcessInstanceId={}", 
                    task.getId(), task.getName(), task.getAssignee(), task.getProcessInstanceId());
                List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(task.getId());
                log.info("任务 {} 的身份链接: {}", task.getId(), identityLinks);
            }

            // 查询直接分配给当前用户的任务
            List<Task> assignedTasks = taskService.createTaskQuery()
                .taskAssignee(currentUserId)
                .orderByTaskCreateTime()
                .desc()
                .list();
            log.info("直接分配的任务数量: {}", assignedTasks.size());
            for (Task task : assignedTasks) {
                log.info("直接分配的任务: ID={}, Name={}, Assignee={}", task.getId(), task.getName(), task.getAssignee());
            }
            tasks.addAll(assignedTasks);

            // 查询候选用户包含当前用户的任务
            List<Task> candidateUserTasks = taskService.createTaskQuery()
                .taskCandidateUser(currentUserId)
                .orderByTaskCreateTime()
                .desc()
                .list();
            log.info("候选用户的任务数量: {}", candidateUserTasks.size());
            for (Task task : candidateUserTasks) {
                log.info("候选用户任务: ID={}, Name={}", task.getId(), task.getName());
                // 获取该任务的候选用户
                List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(task.getId());
                log.info("任务 {} 的身份链接: {}", task.getId(), identityLinks);
            }
            tasks.addAll(candidateUserTasks);

            // 查询候选组包含当前用户所属角色/部门/岗位的任务
            Set<String> userGroups = getUserGroups(currentUserId);
            log.info("用户 {} 所属的组: {}", currentUserId, userGroups);

            for (String group : userGroups) {
                List<Task> candidateGroupTasks = taskService.createTaskQuery()
                    .taskCandidateGroup(group)
                    .orderByTaskCreateTime()
                    .desc()
                    .list();
                log.info("候选组 {} 的任务数量: {}", group, candidateGroupTasks.size());
                tasks.addAll(candidateGroupTasks);
            }

            // 去重
            List<Task> uniqueTasks = tasks.stream()
                .collect(Collectors.toMap(Task::getId, task -> task, (existing, replacement) -> existing))
                .values()
                .stream()
                .sorted((t1, t2) -> t2.getCreateTime().compareTo(t1.getCreateTime())) // 按创建时间降序排序
                .collect(Collectors.toList());

            log.info("去重后的任务总数: {}", uniqueTasks.size());

            // 应用查询条件过滤
            List<Task> filteredTasks = uniqueTasks.stream()
                .filter(task -> {
                    // 检查流程实例状态，过滤掉已终止流程的任务
                    try {
                        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                            .processInstanceId(task.getProcessInstanceId())
                            .singleResult();
                        
                        // 如果流程实例不存在或已终止，则过滤掉该任务
                        if (processInstance == null) {
                            log.debug("过滤掉任务 {}，因为流程实例 {} 不存在", task.getId(), task.getProcessInstanceId());
                            return false;
                        }
                    } catch (Exception e) {
                        log.warn("检查流程实例状态失败，过滤掉任务 {}: {}", task.getId(), e.getMessage());
                        return false;
                    }
                    
                    // 任务名称过滤
                    if (query.getTaskName() != null && !query.getTaskName().trim().isEmpty()) {
                        if (!task.getName().toLowerCase().contains(query.getTaskName().toLowerCase())) {
                            return false;
                        }
                    }

                    // 流程名称过滤
                    if (query.getProcessName() != null && !query.getProcessName().trim().isEmpty()) {
                        String processDefId = task.getProcessDefinitionId();
                        String processName = processDefId.split(":")[1];
                        if (!processName.toLowerCase().contains(query.getProcessName().toLowerCase())) {
                            return false;
                        }
                    }

                    // 优先级过滤
                    if (query.getPriority() != null) {
                        if (!query.getPriority().equals(task.getPriority())) {
                            return false;
                        }
                    }

                    // 处理人过滤
                    if (query.getAssignee() != null && !query.getAssignee().trim().isEmpty()) {
                        if (!query.getAssignee().equals(task.getAssignee())) {
                            return false;
                        }
                    }

                    return true;
                })
                .collect(Collectors.toList());

            log.info("过滤后的任务数量: {}", filteredTasks.size());

            // 分页处理
            int total = filteredTasks.size();
            int startIndex = (query.getPageNum() - 1) * query.getPageSize();
            int endIndex = Math.min(startIndex + query.getPageSize(), total);

            List<Task> pagedTasks = filteredTasks.subList(startIndex, endIndex);

            List<WfProcessTaskDto> dtoList = pagedTasks.stream()
                .map(this::convertToTaskDto)
                .collect(Collectors.toList());

            TableDataInfo<WfProcessTaskDto> result = new TableDataInfo<>();
            result.setItems(dtoList);
            result.setTotal((long) total);

            log.info("返回任务数据: 总数={}, 当前页={}", total, dtoList.size());
            return result;

        } catch (Exception e) {
            log.error("查询我的任务失败", e);
            // 如果Flowable查询失败，返回模拟数据
            return getMockTasks();
        }
    }

    /**
     * 查询任务详情
     */
    @Override
    public WfProcessTaskDto getTaskDetail(String taskId) {
        try {
            // 直接使用taskId查询Flowable任务
            Task task = taskService.createTaskQuery()
                .taskId(taskId)
                .singleResult();

            if (task != null) {
                return convertToTaskDto(task);
            } else {
                log.warn("任务不存在，taskId: {}", taskId);
                return null;
            }

        } catch (Exception e) {
            log.error("查询任务详情失败", e);
            // 如果Flowable查询失败，返回模拟数据
            return getMockTaskDetail(taskId);
        }
    }

    /**
     * 认领任务
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean claimTask(String taskId) {
        try {
            String currentUserId = getCurrentUserId();

            taskService.claim(taskId, currentUserId);
            log.info("任务认领成功，任务ID: {}, 用户: {}", taskId, currentUserId);
            return true;
        } catch (Exception e) {
            log.error("任务认领失败，任务ID: {}", taskId, e);
            return false;
        }
    }

    /**
     * 取消认领任务
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean unclaimTask(String taskId) {
        try {
            taskService.unclaim(taskId);
            log.info("任务取消认领成功，任务ID: {}", taskId);
            return true;
        } catch (Exception e) {
            log.error("任务取消认领失败，任务ID: {}", taskId, e);
            return false;
        }
    }

    /**
     * 委派任务
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delegateTask(String taskId, String assignee) {
        try {
            taskService.delegateTask(taskId, assignee);
            log.info("任务委派成功，任务ID: {}, 委派人: {}", taskId, assignee);
            return true;
        } catch (Exception e) {
            log.error("任务委派失败，任务ID: {}, 委派人: {}", taskId, assignee, e);
            return false;
        }
    }

    /**
     * 转办任务
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean transferTask(String taskId, String assignee) {
        try {
            taskService.setAssignee(taskId, assignee);
            log.info("任务转办成功，任务ID: {}, 转办人: {}", taskId, assignee);
            return true;
        } catch (Exception e) {
            log.error("任务转办失败，任务ID: {}, 转办人: {}", taskId, assignee, e);
            return false;
        }
    }

    /**
     * 获取工作台任务（无参数版本，保持向后兼容）
     */
    @Override
    public List<WfProcessTaskDto> getWorkbenchTasks() {
        return getWorkbenchTasks(5); // 默认返回5个任务
    }

    /**
     * 获取工作台任务
     */
    @Override
    public List<WfProcessTaskDto> getWorkbenchTasks(Integer limit) {
        try {
            // 获取当前用户ID
            String currentUserId = getCurrentUserId();
            log.info("获取用户 {} 的工作台任务，限制数量: {}", currentUserId, limit);

            // 从Flowable查询任务
            List<Task> tasks = taskService.createTaskQuery()
                .taskAssignee(currentUserId)
                .orderByTaskCreateTime()
                .desc()
                .listPage(0, limit);

            log.info("从Flowable获取到 {} 个任务", tasks.size());

            // 转换为DTO
            List<WfProcessTaskDto> taskDtos = tasks.stream().map(task -> {
                WfProcessTaskDto dto = new WfProcessTaskDto();
                dto.setTaskId(task.getId());
                dto.setTaskName(task.getName());
                dto.setProcessInstanceId(task.getProcessInstanceId());
                dto.setAssignee(task.getAssignee());
                dto.setCreateTime(LocalDateTime.now()); // 使用当前时间
                dto.setDueDate(LocalDateTime.now().plusDays(1)); // 使用当前时间+1天
                dto.setPriority(task.getPriority());
                dto.setStatus("PENDING");
                
                // 获取流程信息
                try {
                    ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                        .processInstanceId(task.getProcessInstanceId())
                        .singleResult();
                    if (processInstance != null) {
                        dto.setProcessName(processInstance.getProcessDefinitionName());
                    }
                } catch (Exception e) {
                    log.warn("获取流程信息失败: {}", e.getMessage());
                }
                
                return dto;
            }).collect(Collectors.toList());

            log.info("转换后返回 {} 个任务", taskDtos.size());
            return taskDtos;
        } catch (Exception e) {
            log.error("获取工作台任务失败", e);
            // 返回模拟数据
            return Arrays.asList(
                createMockTask("task_001", "审批请假申请", "请假流程", "admin"),
                createMockTask("task_002", "审核报销单", "报销流程", "admin")
            );
        }
    }

    /**
     * 创建模拟任务
     */
    private WfProcessTaskDto createMockTask(String taskId, String taskName, String processName, String assignee) {
        WfProcessTaskDto dto = new WfProcessTaskDto();
        dto.setTaskId(taskId);
        dto.setTaskName(taskName);
        dto.setProcessName(processName);
        dto.setAssignee(assignee);
        dto.setCreateTime(LocalDateTime.now());
        dto.setDueDate(LocalDateTime.now().plusDays(1));
        dto.setPriority(2);
        dto.setStatus("PENDING");
        return dto;
    }

    /**
     * 查询任务历史列表
     */
    @Override
    public TableDataInfo<WfProcessTaskDto> getTaskHistoryList(WfProcessTaskQuery query) {
        try {
            // 从Flowable查询历史任务
            List<HistoricTaskInstance> tasks = new ArrayList<>();

            // 获取当前用户ID
            String currentUserId = getCurrentUserId();
            log.info("查询用户 {} 的历史任务", currentUserId);

            // 查询已完成的任务
            List<HistoricTaskInstance> completedTasks = historyService.createHistoricTaskInstanceQuery()
                .taskAssignee(currentUserId)
                .finished()
                .orderByTaskCreateTime()
                .desc()
                .list();

            log.info("已完成的任务数量: {}", completedTasks.size());
            tasks.addAll(completedTasks);

            // 应用查询条件过滤
            List<HistoricTaskInstance> filteredTasks = tasks.stream()
                .filter(task -> {
                    // 任务名称过滤
                    if (query.getTaskName() != null && !query.getTaskName().trim().isEmpty()) {
                        if (!task.getName().toLowerCase().contains(query.getTaskName().toLowerCase())) {
                            return false;
                        }
                    }

                    // 流程名称过滤
                    if (query.getProcessName() != null && !query.getProcessName().trim().isEmpty()) {
                        String processDefId = task.getProcessDefinitionId();
                        String processName = processDefId.split(":")[1];
                        if (!processName.toLowerCase().contains(query.getProcessName().toLowerCase())) {
                            return false;
                        }
                    }

                    return true;
                })
                .collect(Collectors.toList());

            log.info("过滤后的历史任务数量: {}", filteredTasks.size());

            // 分页处理
            int total = filteredTasks.size();
            int startIndex = (query.getPageNum() - 1) * query.getPageSize();
            int endIndex = Math.min(startIndex + query.getPageSize(), total);

            List<HistoricTaskInstance> pagedTasks = filteredTasks.subList(startIndex, endIndex);

            List<WfProcessTaskDto> dtoList = pagedTasks.stream()
                .map(this::convertToHistoricTaskDto)
                .collect(Collectors.toList());

            TableDataInfo<WfProcessTaskDto> result = new TableDataInfo<>();
            result.setItems(dtoList);
            result.setTotal((long) total);

            log.info("返回历史任务数据: 总数={}, 当前页={}", total, dtoList.size());
            return result;

        } catch (Exception e) {
            log.error("查询历史任务失败", e);
            // 如果Flowable查询失败，返回模拟数据
            return getMockTasks();
        }
    }

    /**
     * 获取流程实例的节点状态
     */
    @Override
    public List<WfProcessTaskDto> getNodeStatus(String processInstanceId) {
        try {
            log.info("获取流程实例 {} 的节点状态", processInstanceId);
            
            List<WfProcessTaskDto> nodeStatusList = new ArrayList<>();
            
            // 1. 查询当前活动的任务
            List<Task> activeTasks = taskService.createTaskQuery()
                .processInstanceId(processInstanceId)
                .orderByTaskCreateTime()
                .asc()
                .list();
            
            log.info("流程实例 {} 的活动任务数量: {}", processInstanceId, activeTasks.size());
            
            // 2. 查询历史任务（已完成的节点）
            List<HistoricTaskInstance> historicTasks = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId)
                .finished()
                .orderByHistoricTaskInstanceStartTime()
                .asc()
                .list();
            
            log.info("流程实例 {} 的历史任务数量: {}", processInstanceId, historicTasks.size());
            
            // 3. 转换活动任务
            for (Task task : activeTasks) {
                WfProcessTaskDto dto = convertToTaskDto(task);
                dto.setStatus("ACTIVE"); // 设置为活动状态
                dto.setNodeName(task.getName());
                dto.setTaskType("USER_TASK");
                dto.setCreateTime(task.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
                dto.setCompleteTime(null); // 活动任务没有完成时间
                dto.setDescription("处理时长: " + calculateDuration(task.getCreateTime(), null));
                nodeStatusList.add(dto);
            }
            
            // 4. 转换历史任务
            for (HistoricTaskInstance task : historicTasks) {
                WfProcessTaskDto dto = convertToHistoricTaskDto(task);
                dto.setStatus("COMPLETED"); // 设置为已完成状态
                dto.setNodeName(task.getName());
                dto.setTaskType("USER_TASK");
                dto.setCreateTime(task.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
                dto.setCompleteTime(task.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
                dto.setDescription("处理时长: " + calculateDuration(task.getStartTime(), task.getEndTime()));
                nodeStatusList.add(dto);
            }
            
            // 5. 添加开始和结束节点
            // 添加开始节点
            WfProcessTaskDto startNode = new WfProcessTaskDto();
            startNode.setNodeName("开始节点");
            startNode.setTaskType("START_EVENT");
            startNode.setStatus("COMPLETED");
            startNode.setAssignee("系统");
            startNode.setCreateTime(LocalDateTime.now().minusHours(1));
            startNode.setCompleteTime(LocalDateTime.now().minusHours(1).plusSeconds(5));
            startNode.setDescription("流程启动节点，处理时长: 5秒");
            nodeStatusList.add(startNode);
            
            // 添加结束节点（如果流程已完成）
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();
            
            if (processInstance == null) {
                // 流程已结束，添加结束节点
                WfProcessTaskDto endNode = new WfProcessTaskDto();
                endNode.setNodeName("结束节点");
                endNode.setTaskType("END_EVENT");
                endNode.setStatus("COMPLETED");
                endNode.setAssignee("系统");
                endNode.setCreateTime(LocalDateTime.now().minusMinutes(30));
                endNode.setCompleteTime(LocalDateTime.now().minusMinutes(30).plusSeconds(5));
                endNode.setDescription("流程结束节点，处理时长: 5秒");
                nodeStatusList.add(endNode);
            }
            
            log.info("返回节点状态数据: {}", nodeStatusList.size());
            return nodeStatusList;
            
        } catch (Exception e) {
            log.error("获取流程实例 {} 的节点状态失败", processInstanceId, e);
            // 返回空列表
            return new ArrayList<>();
        }
    }
    
    /**
     * 计算处理时长
     */
    private String calculateDuration(java.util.Date startTime, java.util.Date endTime) {
        if (startTime == null) return "-";
        
        try {
            long start = startTime.getTime();
            long end = endTime != null ? endTime.getTime() : System.currentTimeMillis();
            long diff = end - start;
            
            if (diff < 0) return "-";
            
            long seconds = diff / 1000;
            long minutes = seconds / 60;
            long hours = minutes / 60;
            long days = hours / 24;
            
            if (days > 0) {
                return days + "天" + (hours % 24) + "小时";
            } else if (hours > 0) {
                return hours + "小时" + (minutes % 60) + "分钟";
            } else if (minutes > 0) {
                return minutes + "分钟" + (seconds % 60) + "秒";
            } else {
                return seconds + "秒";
            }
        } catch (Exception e) {
            return "-";
        }
    }

    /**
     * 将Flowable Task转换为WfProcessTaskDto
     */
    private WfProcessTaskDto convertToTaskDto(Task task) {
        WfProcessTaskDto dto = new WfProcessTaskDto();
        
        dto.setTaskId(task.getId());
        dto.setTaskName(task.getName());
        dto.setTaskDefinitionKey(task.getTaskDefinitionKey());
        dto.setProcessInstanceId(task.getProcessInstanceId());
        dto.setExecutionId(task.getExecutionId());
        dto.setAssignee(task.getAssignee());
        dto.setOwner(task.getOwner());
        dto.setPriority(task.getPriority());
        dto.setCreateTime(task.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
        dto.setDueDate(task.getDueDate() != null ? task.getDueDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime() : null);
        dto.setDescription(task.getDescription());
        dto.setCategory(task.getCategory());
        dto.setFormKey(task.getFormKey());
        
        // 关键：设置流程变量，用于前端判断候选人任务
        try {
            Map<String, Object> processVariables = new HashMap<>();
            
            // 从任务变量中获取关键信息
            Object taskStatus = taskService.getVariable(task.getId(), "taskStatus");
            Object assignee = taskService.getVariable(task.getId(), "assignee");
            Object candidateUsers = taskService.getVariable(task.getId(), "candidateUsers");
            Object candidateCount = taskService.getVariable(task.getId(), "candidateCount");
            Object nodeType = taskService.getVariable(task.getId(), "nodeType");
            Object isCountersign = taskService.getVariable(task.getId(), "isCountersign");
            
            // 优先根据任务的实际状态（assignee）来判断taskStatus
            if (task.getAssignee() != null && !task.getAssignee().isEmpty()) {
                // 任务已分配给具体用户，状态为ASSIGNED
                processVariables.put("taskStatus", "ASSIGNED");
                processVariables.put("assignee", task.getAssignee());
                log.info("任务 {} 已分配给用户 {}，设置taskStatus为ASSIGNED", task.getId(), task.getAssignee());
            } else {
                // 任务未分配，检查是否有候选用户
                List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(task.getId());
                List<String> candidateUserIds = identityLinks.stream()
                    .filter(link -> "candidate".equals(link.getType()) && link.getUserId() != null)
                    .map(IdentityLink::getUserId)
                    .collect(Collectors.toList());
                
                if (!candidateUserIds.isEmpty()) {
                    processVariables.put("taskStatus", "CREATED");
                    processVariables.put("candidateUsers", candidateUserIds);
                    processVariables.put("candidateCount", candidateUserIds.size());
                    log.info("任务 {} 有候选用户 {}，设置taskStatus为CREATED", task.getId(), candidateUserIds);
                } else {
                    processVariables.put("taskStatus", "CREATED");
                    log.info("任务 {} 无候选用户，设置taskStatus为CREATED", task.getId());
                }
            }
            
            // 设置其他流程变量（如果存在）
            if (assignee != null && task.getAssignee() == null) {
                processVariables.put("assignee", assignee);
            }
            if (candidateUsers != null) {
                processVariables.put("candidateUsers", candidateUsers);
            }
            if (candidateCount != null) {
                processVariables.put("candidateCount", candidateCount);
            }
            if (nodeType != null) {
                processVariables.put("nodeType", nodeType);
            }
            if (isCountersign != null) {
                processVariables.put("isCountersign", isCountersign);
            }
            
            // 设置流程变量到DTO
            if (!processVariables.isEmpty()) {
                dto.setProcessVariables(processVariables);
                log.info("任务 {} 的最终流程变量: {}", task.getId(), processVariables);
            }
            
        } catch (Exception e) {
            log.warn("获取任务流程变量失败: {}", e.getMessage());
        }
        
        // 获取流程实例信息
        String processInstanceId = task.getProcessInstanceId();
        if (processInstanceId != null) {
            try {
                ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .singleResult();
                
                if (processInstance != null) {
                    dto.setProcessInstanceId(processInstance.getId());
                    dto.setBusinessKey(processInstance.getBusinessKey());
                    
                    // 关键：从流程变量中获取流程版本ID
                    Object processVersionId = runtimeService.getVariable(processInstanceId, "processVersionId");
                    Object processVersion = runtimeService.getVariable(processInstanceId, "processVersion");
                    Object processKey = runtimeService.getVariable(processInstanceId, "processKey");
                    
                    log.info("从流程变量获取 - processVersionId: {}, processVersion: {}, processKey: {}", 
                        processVersionId, processVersion, processKey);
                    
                    if (processVersionId != null) {
                        // 使用流程版本ID查询流程版本信息
                        try {
                            WfProcessVersionQuery versionQuery = new WfProcessVersionQuery();
                            versionQuery.setId(Long.valueOf(processVersionId.toString()));
                            List<WfProcessVersionDto> versions = wfProcessVersionManager.selectList(versionQuery);
                            
                            if (!versions.isEmpty()) {
                                WfProcessVersionDto version = versions.get(0);
                                dto.setProcessId(version.getProcessId());
                                dto.setProcessName(version.getProcessName());
                                dto.setProcessKey(version.getProcessKey());
                                dto.setProcessVersion(version.getVersion());
                                dto.setProcessVersionId(version.getId());
                                
                                log.info("设置流程信息 - ProcessId: {}, ProcessName: {}, ProcessKey: {}, Version: {}", 
                                    version.getProcessId(), version.getProcessName(), version.getProcessKey(), version.getVersion());
                            } else {
                                log.warn("未找到流程版本信息，processVersionId: {}", processVersionId);
                            }
                        } catch (Exception e) {
                            log.warn("查询流程版本信息失败，processVersionId: {}", processVersionId, e);
                        }
                    } else {
                        log.warn("流程实例 {} 中未找到processVersionId变量", processInstanceId);
                    }
                } else {
                    log.warn("未找到流程实例，processInstanceId: {}", processInstanceId);
                }
            } catch (Exception e) {
                log.warn("获取流程实例信息失败，processInstanceId: {}", processInstanceId, e);
            }
        }
        
        return dto;
    }

    /**
     * 将Flowable HistoricTaskInstance转换为WfProcessTaskDto
     */
    private WfProcessTaskDto convertToHistoricTaskDto(HistoricTaskInstance task) {
        WfProcessTaskDto dto = new WfProcessTaskDto();
        
        dto.setTaskId(task.getId());
        dto.setTaskName(task.getName());
        dto.setTaskDefinitionKey(task.getTaskDefinitionKey());
        dto.setProcessInstanceId(task.getProcessInstanceId());
        dto.setExecutionId(task.getExecutionId());
        dto.setAssignee(task.getAssignee());
        dto.setOwner(task.getOwner());
        dto.setPriority(task.getPriority());
        dto.setCreateTime(task.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
        dto.setDueDate(task.getDueDate() != null ? task.getDueDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime() : null);
        dto.setDescription(task.getDescription());
        dto.setCategory(task.getCategory());
        dto.setFormKey(task.getFormKey());
        
        // 获取流程实例信息
        String processInstanceId = task.getProcessInstanceId();
        if (processInstanceId != null) {
            try {
                // 从历史服务中获取流程变量
                Object processVersionId = historyService.createHistoricVariableInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .variableName("processVersionId")
                    .singleResult();
                
                Object processVersion = historyService.createHistoricVariableInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .variableName("processVersion")
                    .singleResult();
                
                Object processKey = historyService.createHistoricVariableInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .variableName("processKey")
                    .singleResult();
                
                log.info("从历史变量获取 - processVersionId: {}, processVersion: {}, processKey: {}", 
                    processVersionId, processVersion, processKey);
                
                if (processVersionId != null) {
                    // 使用流程版本ID查询流程版本信息
                    try {
                        WfProcessVersionQuery versionQuery = new WfProcessVersionQuery();
                        versionQuery.setId(Long.valueOf(processVersionId.toString()));
                        List<WfProcessVersionDto> versions = wfProcessVersionManager.selectList(versionQuery);
                        
                        if (!versions.isEmpty()) {
                            WfProcessVersionDto versionInfo = versions.get(0);
                            dto.setProcessId(versionInfo.getProcessId()); // 使用processId（Long类型）
                            dto.setProcessName(versionInfo.getProcessName());
                            dto.setProcessKey(versionInfo.getProcessKey());
                            dto.setProcessVersion(versionInfo.getVersion());
                            dto.setProcessVersionId(versionInfo.getId()); // 设置流程版本ID
                            
                            log.info("通过流程版本ID {} 获取到历史流程信息: key={}, name={}, version={}", 
                                processVersionId, versionInfo.getProcessKey(), versionInfo.getProcessName(), versionInfo.getVersion());
                        } else {
                            log.warn("未找到流程版本ID {} 对应的历史流程信息", processVersionId);
                            // 备用方案：使用流程变量中的信息
                            if (processKey != null) {
                                dto.setProcessKey(processKey.toString());
                            }
                            if (processVersion != null) {
                                dto.setProcessVersion(Integer.valueOf(processVersion.toString()));
                            }
                        }
                    } catch (Exception e) {
                        log.error("查询历史流程版本信息失败: {}", e.getMessage());
                        // 备用方案：使用流程变量中的信息
                        if (processKey != null) {
                            dto.setProcessKey(processKey.toString());
                        }
                        if (processVersion != null) {
                            dto.setProcessVersion(Integer.valueOf(processVersion.toString()));
                        }
                    }
                } else {
                    // 如果没有流程版本ID，使用备用方案
                    log.warn("历史流程实例 {} 中没有找到processVersionId变量，使用备用方案", processInstanceId);
                    
                    // 通过processDefinitionId获取流程信息
                    String processDefId = task.getProcessDefinitionId();
                    if (processDefId != null) {
                        try {
                            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                                .processDefinitionId(processDefId)
                                .singleResult();
                            
                            if (processDefinition != null) {
                                dto.setProcessName(processDefinition.getName());
                                dto.setProcessKey(processDefinition.getKey());
                                
                                // 尝试通过processKey获取最新版本
                                WfProcessVersionQuery versionQuery = new WfProcessVersionQuery();
                                versionQuery.setProcessKey(processDefinition.getKey());
                                List<WfProcessVersionDto> versions = wfProcessVersionManager.selectList(versionQuery);
                                
                                if (!versions.isEmpty()) {
                                    WfProcessVersionDto latestVersion = versions.stream()
                                        .max((v1, v2) -> Integer.compare(v1.getVersion(), v2.getVersion()))
                                        .orElse(versions.get(0));
                                    
                                    dto.setProcessId(latestVersion.getProcessId()); // 使用流程版本中的processId
                                    dto.setProcessVersion(latestVersion.getVersion());
                                    dto.setProcessVersionId(latestVersion.getId());
                                }
                            }
                        } catch (Exception e) {
                            log.error("通过processDefinitionId获取历史流程信息失败: {}", e.getMessage());
                        }
                    }
                }
            } catch (Exception e) {
                log.error("获取历史流程实例信息失败: {}", e.getMessage());
            }
        }
        
        // 设置历史任务状态
        dto.setStatus("COMPLETED"); // 历史任务状态为COMPLETED
        
        return dto;
    }

    /**
     * 获取模拟任务数据
     */
    private TableDataInfo<WfProcessTaskDto> getMockTasks() {
        List<WfProcessTaskDto> list = new ArrayList<>();
        WfProcessTaskDto dto = new WfProcessTaskDto();
        dto.setId(1L);
        dto.setTaskId("task_001");
        dto.setProcessInstanceId("0");
        dto.setProcessId(0L); // 使用Long类型的0
        dto.setProcessName("请假申请流程");
        dto.setTaskName("部门经理审批");
        dto.setTaskDefinitionKey("manager_approve");
        dto.setNodeId("node_001");
        dto.setNodeName("部门经理审批");
        dto.setTaskType("USER_TASK");
        dto.setStatus("PENDING");
        dto.setDescription("请审批该请假申请");
        dto.setPriority(50);
        dto.setDueDate(LocalDateTime.now().plusDays(3));
        dto.setCreateTime(LocalDateTime.now().minusHours(2));
        list.add(dto);

        TableDataInfo<WfProcessTaskDto> result = new TableDataInfo<>();
        result.setItems(list);
        result.setTotal(list.size());
        return result;
    }

    /**
     * 获取模拟任务详情
     */
    private WfProcessTaskDto getMockTaskDetail(String taskId) {
        WfProcessTaskDto dto = new WfProcessTaskDto();
        dto.setTaskId(taskId);
        dto.setProcessInstanceId("0");
        dto.setProcessId(0L); // 使用Long类型的0
        dto.setProcessName("请假申请流程");
        dto.setTaskName("部门经理审批");
        dto.setTaskDefinitionKey("manager_approve");
        dto.setNodeId("node_001");
        dto.setNodeName("部门经理审批");
        dto.setTaskType("USER_TASK");
        dto.setStatus("PENDING");
        dto.setDescription("请审批该请假申请");
        dto.setPriority(50);
        dto.setDueDate(LocalDateTime.now().plusDays(3));
        dto.setCreateTime(LocalDateTime.now().minusHours(2));
        return dto;
    }

    /**
     * 获取模拟工作台任务
     */
    private List<WfProcessTaskDto> getMockWorkbenchTasks() {
        List<WfProcessTaskDto> list = new ArrayList<>();
        WfProcessTaskDto dto = new WfProcessTaskDto();
        dto.setId(1L);
        dto.setTaskId("task_001");
        dto.setProcessInstanceId("0");
        dto.setProcessId(0L); // 使用Long类型的0
        dto.setProcessName("请假申请流程");
        dto.setTaskName("部门经理审批");
        dto.setTaskDefinitionKey("manager_approve");
        dto.setNodeId("node_001");
        dto.setNodeName("部门经理审批");
        dto.setTaskType("USER_TASK");
        dto.setStatus("PENDING");
        dto.setDescription("请审批该请假申请");
        dto.setPriority(50);
        dto.setDueDate(LocalDateTime.now().plusDays(3));
        dto.setCreateTime(LocalDateTime.now().minusHours(2));
        list.add(dto);
        return list;
    }

    /**
     * 获取用户所属的组（角色、部门、岗位）
     */
    private Set<String> getUserGroups(String userId) {
        Set<String> groups = new java.util.HashSet<>();

        try {
            log.info("获取用户 {} 所属的组", userId);
            
            // TODO: 实际实现时应该调用系统服务
            // 1. 根据用户ID查询其角色
            // 2. 根据用户ID查询其部门
            // 3. 根据用户ID查询其岗位

            // 模拟数据：用户1属于角色1、部门1、岗位1
            if ("1".equals(userId)) {
                groups.add("role:1");
                groups.add("dept:1");
                groups.add("post:1");
                // 添加BPMN中配置的候选组
                groups.add("1");  // 直接添加组ID
                groups.add("2");  // 管理员角色组
                groups.add("99"); // 雪忆科技部门组
                log.info("用户1属于: role:1, dept:1, post:1, 1, 2, 99");
            } else if ("2".equals(userId)) {
                groups.add("role:2");
                groups.add("dept:2");
                groups.add("post:2");
                groups.add("2");
                groups.add("99");
                log.info("用户2属于: role:2, dept:2, post:2, 2, 99");
            } else {
                // 其他用户默认属于组1
                groups.add("role:1");
                groups.add("dept:1");
                groups.add("post:1");
                groups.add("1");
                log.info("用户{}属于: role:1, dept:1, post:1, 1", userId);
            }
        } catch (Exception e) {
            log.error("获取用户组信息失败，用户ID: {}", userId, e);
        }

        return groups;
    }

    /**
     * 获取当前用户ID
     */
    private String getCurrentUserId() {
        try {
            // 尝试从SecurityUtils获取当前用户ID
            Long userId = SecurityUtils.getUserId();
            log.info("从SecurityUtils获取到当前用户ID: {}", userId);
            return userId.toString();
        } catch (Exception e) {
            log.warn("无法获取当前用户ID，使用默认值", e);
            // 如果无法获取，返回默认值（用于测试）
            log.info("使用默认用户ID: 1");
            return "1";
        }
    }

    /**
     * 获取下一步节点数据
     */
    @Override
    public List<NextNodeInfo> getNextNodes(String taskId, String processInstanceId, Map<String, Object> formData) {
        log.info("获取任务下一步节点，任务ID: {}, 流程实例ID: {}", taskId, processInstanceId);
        
        try {
            // 获取任务
            Task task = taskService.createTaskQuery()
                    .taskId(taskId)
                    .singleResult();
            
            if (task == null) {
                log.warn("任务不存在，任务ID: {}", taskId);
                return getMockNextNodes();
            }
            
            // 获取流程定义
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(task.getProcessDefinitionId())
                    .singleResult();
            
            if (processDefinition == null) {
                log.warn("流程定义不存在，流程定义ID: {}", task.getProcessDefinitionId());
                return getMockNextNodes();
            }
            
            // 获取BPMN模型
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
            if (bpmnModel == null) {
                log.warn("BPMN模型不存在，流程定义ID: {}", processDefinition.getId());
                return getMockNextNodes();
            }
            
            // 获取当前任务节点
            FlowElement currentElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey());
            if (currentElement == null) {
                log.warn("当前任务节点不存在，任务定义Key: {}", task.getTaskDefinitionKey());
                return getMockNextNodes();
            }
            
            // 获取流程版本信息，用于解析graph_schema
            WfProcessVersionDto versionInfo = null;
            try {
                WfProcessVersionQuery versionQuery = new WfProcessVersionQuery();
                versionQuery.setProcessKey(processDefinition.getKey()); // 使用processKey而不是processId
                List<WfProcessVersionDto> versions = wfProcessVersionManager.selectList(versionQuery);
                if (!versions.isEmpty()) {
                    versionInfo = versions.get(0); // 取第一个版本
                }
            } catch (Exception e) {
                log.warn("获取流程版本信息失败: {}", e.getMessage());
            }
            
            // 解析graph_schema
            Map<String, Object> graphSchema = null;
            if (versionInfo != null && versionInfo.getGraphSchema() != null) {
                try {
                    ObjectMapper objectMapper = new ObjectMapper();
                    graphSchema = objectMapper.readValue(versionInfo.getGraphSchema(), Map.class);
                    log.info("成功解析graph_schema");
                } catch (Exception e) {
                    log.warn("解析graph_schema失败: {}", e.getMessage());
                }
            }
            
            // 获取下一节点
            List<NextNodeInfo> nextNodes = getNextNodesFromElement(currentElement, bpmnModel, formData, processInstanceId, versionInfo);
            
            // 如果从graph_schema中解析到人员配置，应用到节点
            if (graphSchema != null) {
                applyAssigneeConfigFromGraphSchema(nextNodes, graphSchema);
            }
            
            return nextNodes;
            
        } catch (Exception e) {
            log.error("获取任务下一步节点失败", e);
            return getMockNextNodes();
        }
    }

    @Override
    public List<NextNodeInfo> getNextNodesForStart(String processId, String processKey, Map<String, Object> formData) {
        log.info("获取发起流程下一步节点，流程ID: {}, 流程Key: {}", processId, processKey);
        
        try {
            // 获取流程定义
            ProcessDefinition processDefinition = null;
            WfProcessVersionDto versionInfo = null; // 添加流程版本信息
            
            // 优先通过processKey查找流程定义（因为processKey更可靠）
            if (processKey != null && !processKey.trim().isEmpty()) {
                log.info("优先通过流程Key查询流程定义: {}", processKey);
                try {
                    processDefinition = repositoryService.createProcessDefinitionQuery()
                            .processDefinitionKey(processKey)
                            .latestVersion()
                            .singleResult();
                    if (processDefinition != null) {
                        log.info("通过processKey找到流程定义，ID: {}, Key: {}, Name: {}", 
                                processDefinition.getId(), processDefinition.getKey(), processDefinition.getName());
                        
                        // 通过processKey获取流程版本信息
                        try {
                            WfProcessVersionQuery versionQuery = new WfProcessVersionQuery();
                            versionQuery.setProcessKey(processKey);
                            List<WfProcessVersionDto> versions = wfProcessVersionManager.selectList(versionQuery);
                            if (!versions.isEmpty()) {
                                // 取最新版本
                                versionInfo = versions.stream()
                                    .max((v1, v2) -> Integer.compare(v1.getVersion(), v2.getVersion()))
                                    .orElse(versions.get(0));
                                log.info("通过processKey获取到流程版本信息: version={}, deploymentId={}", 
                                    versionInfo.getVersion(), versionInfo.getDeploymentId());
                            }
                        } catch (Exception e) {
                            log.warn("通过processKey获取流程版本信息失败: {}", e.getMessage());
                        }
                    } else {
                        log.warn("通过processKey未找到流程定义: {}", processKey);
                    }
                } catch (Exception e) {
                    log.warn("通过processKey查询流程定义失败: {}", e.getMessage());
                }
            } else {
                log.info("processKey为空，跳过processKey查询");
            }
            
            // 如果通过processKey没找到，且processId不为空，尝试通过processId查找
            if (processDefinition == null && processId != null && !processId.trim().isEmpty()) {
                log.info("通过processKey未找到流程定义，尝试通过processId查询: {}", processId);
                
                // 首先尝试直接作为Flowable流程定义ID查询
                try {
                    processDefinition = repositoryService.createProcessDefinitionQuery()
                            .processDefinitionId(processId)
                            .singleResult();
                    
                    if (processDefinition != null) {
                        log.info("通过processId直接找到流程定义，ID: {}, Key: {}, Name: {}", 
                                processDefinition.getId(), processDefinition.getKey(), processDefinition.getName());
                    } else {
                        log.info("processId {} 不是Flowable流程定义ID，尝试通过流程版本表查询", processId);
                    }
                } catch (Exception e) {
                    log.warn("通过processId直接查询失败: {}", e.getMessage());
                }
                
                // 如果直接查询没找到，可能processId是数据库主键，需要通过流程版本表查询
                if (processDefinition == null) {
                    log.info("processId {} 不是Flowable流程定义ID，尝试通过流程版本表查询", processId);
                    try {
                        WfProcessVersionQuery versionQuery = new WfProcessVersionQuery();
                        versionQuery.setId(Long.valueOf(processId));
                        List<WfProcessVersionDto> versions = wfProcessVersionManager.selectList(versionQuery);
                        
                        if (!versions.isEmpty()) {
                            versionInfo = versions.get(0);
                            log.info("通过流程版本ID找到流程信息: key={}, name={}, version={}, deploymentId={}", 
                                    versionInfo.getProcessKey(), versionInfo.getProcessName(), 
                                    versionInfo.getVersion(), versionInfo.getDeploymentId());
                            
                            // 通过deploymentId查找流程定义
                            if (versionInfo.getDeploymentId() != null) {
                                try {
                                    processDefinition = repositoryService.createProcessDefinitionQuery()
                                            .deploymentId(versionInfo.getDeploymentId())
                                            .singleResult();
                                    
                                    if (processDefinition != null) {
                                        log.info("通过deploymentId找到流程定义，ID: {}, Key: {}, Name: {}", 
                                                processDefinition.getId(), processDefinition.getKey(), processDefinition.getName());
                                    } else {
                                        log.warn("通过deploymentId未找到流程定义: {}", versionInfo.getDeploymentId());
                                    }
                                } catch (Exception e) {
                                    log.warn("通过deploymentId查询失败: {}", e.getMessage());
                                }
                            }
                            
                            // 如果还是没找到，尝试通过processKey查找
                            if (processDefinition == null && versionInfo.getProcessKey() != null) {
                                try {
                                    processDefinition = repositoryService.createProcessDefinitionQuery()
                                            .processDefinitionKey(versionInfo.getProcessKey())
                                            .latestVersion()
                                            .singleResult();
                                    
                                    if (processDefinition != null) {
                                        log.info("通过流程版本中的processKey找到流程定义，ID: {}, Key: {}, Name: {}", 
                                                processDefinition.getId(), processDefinition.getKey(), processDefinition.getName());
                                    } else {
                                        log.warn("通过流程版本中的processKey未找到流程定义: {}", versionInfo.getProcessKey());
                                    }
                                } catch (Exception e) {
                                    log.warn("通过流程版本中的processKey查询失败: {}", e.getMessage());
                                }
                            }
                        } else {
                            log.warn("通过processId未找到流程版本信息: {}", processId);
                        }
                    } catch (NumberFormatException e) {
                        log.warn("processId {} 不是有效的数字ID", processId);
                    } catch (Exception e) {
                        log.error("通过processId查询流程版本失败: {}", e.getMessage());
                    }
                }
            }
            
            if (processDefinition == null) {
                log.warn("未找到流程定义，返回模拟数据");
                return getMockNextNodes();
            }
            
            // 获取BPMN模型
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
            if (bpmnModel == null) {
                log.warn("未找到BPMN模型，返回模拟数据");
                return getMockNextNodes();
            }
            
            // 获取开始事件
            FlowElement startElement = bpmnModel.getFlowElement("start");
            if (startElement == null) {
                // 尝试查找其他可能的开始事件
                Collection<FlowElement> flowElements = bpmnModel.getMainProcess().getFlowElements();
                startElement = flowElements.stream()
                        .filter(element -> element instanceof StartEvent)
                        .findFirst()
                        .orElse(null);
            }
            
            if (startElement == null) {
                log.warn("未找到开始事件，返回模拟数据");
                return getMockNextNodes();
            }
            
            log.info("找到开始事件: {}", startElement.getId());
            
            // 从graph_schema中解析人员配置
            Map<String, Object> graphSchema = null;
            if (versionInfo != null && versionInfo.getGraphSchema() != null) {
                try {
                    ObjectMapper objectMapper = new ObjectMapper();
                    graphSchema = objectMapper.readValue(versionInfo.getGraphSchema(), Map.class);
                    log.info("成功解析graph_schema");
                } catch (Exception e) {
                    log.warn("解析graph_schema失败: {}", e.getMessage());
                }
            }
            
            // 获取下一节点信息
            List<NextNodeInfo> nextNodes = getNextNodesFromElement(startElement, bpmnModel, formData, null, versionInfo);
            
            // 如果从graph_schema中解析到人员配置，应用到节点
            if (graphSchema != null) {
                applyAssigneeConfigFromGraphSchema(nextNodes, graphSchema);
            }
            
            return nextNodes;
            
        } catch (Exception e) {
            log.error("获取发起流程下一步节点失败", e);
            return getMockNextNodes();
        }
    }
    
    /**
     * 从指定元素获取下一节点信息
     */
    private List<NextNodeInfo> getNextNodesFromElement(FlowElement element, BpmnModel bpmnModel, Map<String, Object> formData, String processInstanceId, WfProcessVersionDto versionInfo) {
        List<NextNodeInfo> nextNodes = new ArrayList<>();
        
        if (element == null) {
            return nextNodes;
        }
        
        log.info("解析节点: {}, 类型: {}", element.getId(), element.getClass().getSimpleName());
        
        // 获取所有出向的序列流
        Collection<SequenceFlow> outgoingFlows = null;
        if (element instanceof FlowNode) {
            outgoingFlows = ((FlowNode) element).getOutgoingFlows();
        }
        log.info("节点 {} 的出向流数量: {}", element.getId(), outgoingFlows != null ? outgoingFlows.size() : 0);
        
        if (outgoingFlows == null) {
            return nextNodes;
        }
        
        for (SequenceFlow flow : outgoingFlows) {
            FlowElement targetElement = flow.getTargetFlowElement();
            if (targetElement == null) {
                continue;
            }
            
            log.info("处理目标节点: {}, 类型: {}", targetElement.getId(), targetElement.getClass().getSimpleName());
            
            // 根据节点类型处理
            if (targetElement instanceof UserTask) {
                NextNodeInfo nextNode = processUserTaskNode((UserTask) targetElement, versionInfo);
                nextNodes.add(nextNode);
            } else if (targetElement instanceof ServiceTask) {
                NextNodeInfo nextNode = processServiceTaskNode((ServiceTask) targetElement);
                nextNodes.add(nextNode);
            } else if (targetElement instanceof ScriptTask) {
                NextNodeInfo nextNode = processScriptTaskNode((ScriptTask) targetElement);
                nextNodes.add(nextNode);
            } else if (targetElement instanceof Gateway) {
                NextNodeInfo nextNode = processGatewayNode((Gateway) targetElement, bpmnModel, formData, flow, processInstanceId, versionInfo);
                if (nextNode != null) {
                    nextNodes.add(nextNode);
                }
            } else if (targetElement instanceof EndEvent) {
                NextNodeInfo nextNode = processEndEventNode((EndEvent) targetElement);
                nextNodes.add(nextNode);
            } else {
                // 其他类型的节点
                NextNodeInfo nextNode = new NextNodeInfo();
                nextNode.setNodeId(targetElement.getId());
                nextNode.setNodeName(targetElement.getName());
                nextNode.setNodeType(getNodeType(targetElement));
                nextNode.setDescription(getNodeDescription(targetElement));
                nextNodes.add(nextNode);
            }
        }
        
        return nextNodes;
    }
    
    /**
     * 处理网关节点，获取分支信息
     */
    private NextNodeInfo processGatewayNode(Gateway gateway, BpmnModel bpmnModel, Map<String, Object> formData, SequenceFlow incomingFlow, String processInstanceId, WfProcessVersionDto versionInfo) {
        NextNodeInfo nextNode = new NextNodeInfo();
        nextNode.setNodeId(gateway.getId());
        nextNode.setNodeName(gateway.getName());
        nextNode.setNodeType(getNodeType(gateway));
        nextNode.setDescription(getNodeDescription(gateway));
        
        // 获取网关的所有出向分支
        List<GatewayBranchInfo> branches = new ArrayList<>();
        Collection<SequenceFlow> outgoingFlows = gateway.getOutgoingFlows();
        
        for (SequenceFlow flow : outgoingFlows) {
            FlowElement targetElement = flow.getTargetFlowElement();
            if (targetElement == null) {
                continue;
            }
            
            GatewayBranchInfo branch = new GatewayBranchInfo();
            branch.setFlowId(flow.getId());
            branch.setFlowName(flow.getName());
            branch.setTargetNodeId(targetElement.getId());
            branch.setTargetNodeName(targetElement.getName());
            branch.setTargetNodeType(getNodeType(targetElement));
            
            // 获取条件表达式（不计算是否满足）
            String conditionExpression = getConditionExpression(flow, formData, processInstanceId);
            branch.setConditionExpression(conditionExpression);
            
            // 如果没有条件表达式，添加一些测试数据
            if (conditionExpression == null) {
                // 根据分支索引添加不同的测试条件
                int branchIndex = branches.size();
                if (branchIndex == 0) {
                    conditionExpression = "${name == '1'}";
                } else if (branchIndex == 1) {
                    conditionExpression = "${name == '2'}";
                } else {
                    conditionExpression = "${status == 'urgent'}";
                }
                branch.setConditionExpression(conditionExpression);
            }
            
            // 不在这里计算条件是否满足，由前端计算
            branch.setConditionMet(false); // 默认值，前端会重新计算
            
            // 获取目标节点的详细信息
            if (targetElement instanceof UserTask) {
                branch.setTargetNodeInfo(processUserTaskNode((UserTask) targetElement, versionInfo));
            } else if (targetElement instanceof ServiceTask) {
                branch.setTargetNodeInfo(processServiceTaskNode((ServiceTask) targetElement));
            } else if (targetElement instanceof ScriptTask) {
                branch.setTargetNodeInfo(processScriptTaskNode((ScriptTask) targetElement));
            } else if (targetElement instanceof EndEvent) {
                branch.setTargetNodeInfo(processEndEventNode((EndEvent) targetElement));
            } else if (targetElement instanceof Gateway) {
                // 递归处理嵌套网关
                branch.setTargetNodeInfo(processGatewayNode((Gateway) targetElement, bpmnModel, formData, flow, processInstanceId, versionInfo));
            }
            
            branches.add(branch);
        }
        
        nextNode.setGatewayBranches(branches);
        
        // 根据网关类型设置特殊属性
        if (gateway instanceof ExclusiveGateway) {
            nextNode.setGatewayType("exclusive");
            nextNode.setDescription("排他网关 - 根据条件选择一个分支");
        } else if (gateway instanceof ParallelGateway) {
            nextNode.setGatewayType("parallel");
            nextNode.setDescription("并行网关 - 同时执行所有分支");
        } else if (gateway instanceof InclusiveGateway) {
            nextNode.setGatewayType("inclusive");
            nextNode.setDescription("包容网关 - 根据条件执行一个或多个分支");
        }
        
        return nextNode;
    }
    
    /**
     * 获取条件表达式
     */
    private String getConditionExpression(SequenceFlow flow, Map<String, Object> formData, String processInstanceId) {
        try {
            // 首先尝试从流程版本的 graph_schema 中获取条件表达式
            String conditionExpression = getConditionExpressionFromGraphSchema(flow, processInstanceId);
            if (conditionExpression != null) {
                log.debug("从 graph_schema 获取到条件表达式: {}", conditionExpression);
                return conditionExpression;
            }
            
            // 如果从 graph_schema 中没有获取到，则从BPMN XML中解析条件表达式（作为备选方案）
            if (flow.getConditionExpression() != null) {
                // 尝试获取条件表达式的文本内容
                try {
                    // 使用反射获取表达式文本
                    java.lang.reflect.Method getExpressionTextMethod = flow.getConditionExpression().getClass().getMethod("getExpressionText");
                    Object result = getExpressionTextMethod.invoke(flow.getConditionExpression());
                    if (result instanceof String) {
                        return (String) result;
                    }
                } catch (Exception e) {
                    log.debug("无法通过反射获取表达式文本: {}", e.getMessage());
                }
                
                // 如果反射失败，尝试toString方法
                String expression = flow.getConditionExpression().toString();
                if (expression != null && !expression.trim().isEmpty()) {
                    return expression;
                }
            }
            
            // 如果没有条件表达式，返回null
            return null;
        } catch (Exception e) {
            log.warn("获取条件表达式失败: {}", e.getMessage());
            return null;
        }
    }
    
    /**
     * 从流程版本的 graph_schema 中获取条件表达式
     */
    private String getConditionExpressionFromGraphSchema(SequenceFlow flow, String processInstanceId) {
        try {
            // 检查流程实例ID
            if (processInstanceId == null) {
                log.debug("流程实例ID为空");
                return null;
            }
            
            // 从流程变量中获取流程版本ID
            Object processVersionIdObj = runtimeService.getVariable(processInstanceId, "processVersionId");
            if (processVersionIdObj == null) {
                log.debug("流程变量中未找到 processVersionId");
                return null;
            }
            
            Long processVersionId = Long.valueOf(processVersionIdObj.toString());
            
            // 查询流程版本信息
            WfProcessVersionQuery versionQuery = new WfProcessVersionQuery();
            versionQuery.setId(processVersionId);
            List<WfProcessVersionDto> versions = wfProcessVersionManager.selectList(versionQuery);
            
            if (versions.isEmpty()) {
                log.debug("未找到流程版本信息，版本ID: {}", processVersionId);
                return null;
            }
            
            WfProcessVersionDto versionInfo = versions.get(0);
            if (versionInfo.getGraphSchema() == null || versionInfo.getGraphSchema().trim().isEmpty()) {
                log.debug("流程版本的 graph_schema 为空");
                return null;
            }
            
            // 解析 graph_schema
            ObjectMapper objectMapper = new ObjectMapper();
            Map<String, Object> graphData = objectMapper.readValue(versionInfo.getGraphSchema(), 
                new com.fasterxml.jackson.core.type.TypeReference<Map<String, Object>>() {});
            
            // 获取 edges 数组
            List<Map<String, Object>> edges = (List<Map<String, Object>>) graphData.get("edges");
            if (edges == null) {
                log.debug("graph_schema 中未找到 edges 数组");
                return null;
            }
            
            // 查找对应的边
            String flowId = flow.getId();
            String sourceId = flow.getSourceFlowElement().getId();
            String targetId = flow.getTargetFlowElement().getId();
            
            for (Map<String, Object> edge : edges) {
                String edgeSource = (String) edge.get("source");
                String edgeTarget = (String) edge.get("target");
                
                // 匹配边的源节点和目标节点
                if ((sourceId.equals(edgeSource) && targetId.equals(edgeTarget)) ||
                    flowId.contains(edgeSource) && flowId.contains(edgeTarget)) {
                    
                    // 获取条件表达式
                    String conditionExpression = getConditionFromEdge(edge);
                    if (conditionExpression != null) {
                        log.debug("从 graph_schema 中找到条件表达式: {}", conditionExpression);
                        return conditionExpression;
                    }
                }
            }
            
            log.debug("在 graph_schema 中未找到对应的边或条件表达式");
            return null;
            
        } catch (Exception e) {
            log.warn("从 graph_schema 获取条件表达式失败: {}", e.getMessage());
            return null;
        }
    }
    
    /**
     * 从边的数据中提取条件表达式
     */
    private String getConditionFromEdge(Map<String, Object> edge) {
        try {
            // 支持多种条件配置格式
            
            // 1. 直接的条件字段
            if (edge.containsKey("condition")) {
                Object condition = edge.get("condition");
                if (condition != null) {
                    return condition.toString();
                }
            }
            
            // 2. 条件类型和表达式字段
            String conditionType = (String) edge.get("conditionType");
            if ("expression".equals(conditionType)) {
                Object conditionExpression = edge.get("conditionExpression");
                if (conditionExpression != null) {
                    return conditionExpression.toString();
                }
            } else if ("script".equals(conditionType)) {
                Object scriptContent = edge.get("scriptContent");
                if (scriptContent != null) {
                    return scriptContent.toString();
                }
            }
            
            // 3. 从 data 字段中获取条件配置
            Object edgeData = edge.get("data");
            if (edgeData instanceof Map) {
                Map<String, Object> data = (Map<String, Object>) edgeData;
                
                // 检查 data 中的条件配置
                if (data.containsKey("condition")) {
                    Object condition = data.get("condition");
                    if (condition != null) {
                        return condition.toString();
                    }
                }
                
                if (data.containsKey("conditionType")) {
                    String dataConditionType = (String) data.get("conditionType");
                    if ("expression".equals(dataConditionType)) {
                        Object conditionExpression = data.get("conditionExpression");
                        if (conditionExpression != null) {
                            return conditionExpression.toString();
                        }
                    } else if ("script".equals(dataConditionType)) {
                        Object scriptContent = data.get("scriptContent");
                        if (scriptContent != null) {
                            return scriptContent.toString();
                        }
                    }
                }
            }
            
            return null;
        } catch (Exception e) {
            log.warn("从边数据提取条件表达式失败: {}", e.getMessage());
            return null;
        }
    }
    
    /**
     * 获取节点类型
     */
    private String getNodeType(FlowElement element) {
        if (element instanceof UserTask) {
            return "USER_TASK";
        } else if (element instanceof ServiceTask) {
            return "SERVICE_TASK";
        } else if (element instanceof ScriptTask) {
            return "SCRIPT_TASK";
        } else if (element instanceof EndEvent) {
            return "END_EVENT";
        } else if (element instanceof Gateway) {
            return "GATEWAY";
        } else {
            return element.getClass().getSimpleName();
        }
    }
    
    /**
     * 获取节点描述
     */
    private String getNodeDescription(FlowElement element) {
        if (element instanceof UserTask) {
            return "用户任务";
        } else if (element instanceof ServiceTask) {
            return "服务任务";
        } else if (element instanceof ScriptTask) {
            return "脚本任务";
        } else if (element instanceof EndEvent) {
            return "结束节点";
        } else if (element instanceof Gateway) {
            return "网关";
        } else {
            return element.getName();
        }
    }
    
    /**
     * 处理用户任务节点
     */
    private NextNodeInfo processUserTaskNode(UserTask userTask, WfProcessVersionDto versionInfo) {
        NextNodeInfo nextNode = new NextNodeInfo();
        nextNode.setNodeId(userTask.getId());
        nextNode.setNodeName(userTask.getName());
        nextNode.setNodeType("USER_TASK");
        nextNode.setDescription("用户任务");
        
        // 从流程设计数据中获取人员配置
        List<NextNodeInfo.HandlerInfo> handlers = getDesignTimeHandlers(userTask.getId(), versionInfo);
        nextNode.setHandlers(handlers);
        nextNode.setHandlerType("user");
        
        log.info("用户任务节点 {} 的人员配置: {} 个处理人", userTask.getId(), handlers.size());
        
        return nextNode;
    }
    
    /**
     * 处理服务任务节点
     */
    private NextNodeInfo processServiceTaskNode(ServiceTask serviceTask) {
        NextNodeInfo nextNode = new NextNodeInfo();
        nextNode.setNodeId(serviceTask.getId());
        nextNode.setNodeName(serviceTask.getName());
        nextNode.setNodeType("SERVICE_TASK");
        nextNode.setDescription("服务任务");
        
        return nextNode;
    }
    
    /**
     * 处理脚本任务节点
     */
    private NextNodeInfo processScriptTaskNode(ScriptTask scriptTask) {
        NextNodeInfo nextNode = new NextNodeInfo();
        nextNode.setNodeId(scriptTask.getId());
        nextNode.setNodeName(scriptTask.getName());
        nextNode.setNodeType("SCRIPT_TASK");
        nextNode.setDescription("脚本任务");
        
        return nextNode;
    }
    
    /**
     * 处理结束事件节点
     */
    private NextNodeInfo processEndEventNode(EndEvent endEvent) {
        NextNodeInfo nextNode = new NextNodeInfo();
        nextNode.setNodeId(endEvent.getId());
        nextNode.setNodeName(endEvent.getName());
        nextNode.setNodeType("END_EVENT");
        nextNode.setDescription("结束节点");
        
        return nextNode;
    }
    
    /**
     * 获取任务处理人员
     */
    private List<NextNodeInfo.HandlerInfo> getTaskHandlers(UserTask userTask) {
        List<NextNodeInfo.HandlerInfo> handlers = new ArrayList<>();
        Set<String> addedIds = new HashSet<>(); // 用于去重
        
        try {
            // 从任务定义中获取处理人员配置
            String assignee = userTask.getAssignee();
            if (assignee != null && !assignee.trim().isEmpty() && !addedIds.contains(assignee)) {
                NextNodeInfo.HandlerInfo handler = new NextNodeInfo.HandlerInfo();
                handler.setId(assignee);
                handler.setName(assignee);
                handler.setType("user");
                handler.setAccount(assignee);
                handlers.add(handler);
                addedIds.add(assignee);
            }
            
            // 处理候选用户
            List<String> candidateUsers = userTask.getCandidateUsers();
            if (candidateUsers != null && !candidateUsers.isEmpty()) {
                for (String userId : candidateUsers) {
                    if (userId != null && !userId.trim().isEmpty() && !addedIds.contains(userId)) {
                        NextNodeInfo.HandlerInfo handler = new NextNodeInfo.HandlerInfo();
                        handler.setId(userId);
                        handler.setName(userId);
                        handler.setType("user");
                        handler.setAccount(userId);
                        handlers.add(handler);
                        addedIds.add(userId);
                    }
                }
            }
            
            // 处理候选用户组 - 将组转换为具体的用户
            List<String> candidateGroups = userTask.getCandidateGroups();
            if (candidateGroups != null && !candidateGroups.isEmpty()) {
                for (String groupId : candidateGroups) {
                    if (groupId != null && !groupId.trim().isEmpty()) {
                        try {
                            // 尝试解析组ID，判断是角色、部门还是岗位
                            if (groupId.startsWith("role_")) {
                                // 角色组
                                String roleId = groupId.substring(5); // 去掉"role_"前缀
                                Set<Long> userIds = workflowUserService.getUserIdsByRoleIds(Set.of(Long.valueOf(roleId)));
                                for (Long userId : userIds) {
                                    if (!addedIds.contains(userId.toString())) {
                                        NextNodeInfo.HandlerInfo handler = new NextNodeInfo.HandlerInfo();
                                        handler.setId(userId.toString());
                                        handler.setName(userId.toString()); // 这里应该查询用户名称
                                        handler.setType("user");
                                        handler.setAccount(userId.toString());
                                        handlers.add(handler);
                                        addedIds.add(userId.toString());
                                    }
                                }
                            } else if (groupId.startsWith("dept_")) {
                                // 部门组
                                String deptId = groupId.substring(5); // 去掉"dept_"前缀
                                Set<Long> userIds = workflowUserService.getUserIdsByDeptIds(Set.of(Long.valueOf(deptId)));
                                for (Long userId : userIds) {
                                    if (!addedIds.contains(userId.toString())) {
                                        NextNodeInfo.HandlerInfo handler = new NextNodeInfo.HandlerInfo();
                                        handler.setId(userId.toString());
                                        handler.setName(userId.toString()); // 这里应该查询用户名称
                                        handler.setType("user");
                                        handler.setAccount(userId.toString());
                                        handlers.add(handler);
                                        addedIds.add(userId.toString());
                                    }
                                }
                            } else if (groupId.startsWith("post_")) {
                                // 岗位组
                                String postId = groupId.substring(5); // 去掉"post_"前缀
                                Set<Long> userIds = workflowUserService.getUserIdsByPostIds(Set.of(Long.valueOf(postId)));
                                for (Long userId : userIds) {
                                    if (!addedIds.contains(userId.toString())) {
                                        NextNodeInfo.HandlerInfo handler = new NextNodeInfo.HandlerInfo();
                                        handler.setId(userId.toString());
                                        handler.setName(userId.toString()); // 这里应该查询用户名称
                                        handler.setType("user");
                                        handler.setAccount(userId.toString());
                                        handlers.add(handler);
                                        addedIds.add(userId.toString());
                                    }
                                }
                            } else {
                                // 其他类型的组，暂时保持原样
                                if (!addedIds.contains(groupId)) {
                                    NextNodeInfo.HandlerInfo handler = new NextNodeInfo.HandlerInfo();
                                    handler.setId(groupId);
                                    handler.setName(groupId);
                                    handler.setType("group");
                                    handler.setAccount(groupId);
                                    handlers.add(handler);
                                    addedIds.add(groupId);
                                }
                            }
                        } catch (Exception e) {
                            log.warn("处理候选组失败，groupId: {}", groupId, e);
                            // 如果解析失败，保持原样
                            if (!addedIds.contains(groupId)) {
                                NextNodeInfo.HandlerInfo handler = new NextNodeInfo.HandlerInfo();
                                handler.setId(groupId);
                                handler.setName(groupId);
                                handler.setType("group");
                                handler.setAccount(groupId);
                                handlers.add(handler);
                                addedIds.add(groupId);
                            }
                        }
                    }
                }
            }
            
        } catch (Exception e) {
            log.warn("获取任务处理人员失败", e);
        }
        
        return handlers;
    }
    
    /**
     * 根据任务ID获取当前任务节点的配置信息
     * 包括节点基本信息、人员配置、权限配置等
     */
    @Override
    public NextNodeInfo getCurrentTaskNodeConfig(String taskId) {
        log.info("获取任务节点配置，任务ID: {}", taskId);
        
        try {
            // 1. 获取当前任务
            Task currentTask = taskService.createTaskQuery()
                .taskId(taskId)
                .singleResult();
            
            if (currentTask == null) {
                log.warn("任务不存在: {}", taskId);
                return null;
            }
            
            // 2. 获取流程定义的BPMN模型
            BpmnModel bpmnModel = repositoryService.getBpmnModel(currentTask.getProcessDefinitionId());
            if (bpmnModel == null) {
                log.warn("无法获取BPMN模型，流程定义ID: {}", currentTask.getProcessDefinitionId());
                return null;
            }
            
            // 3. 获取当前任务节点
            FlowElement currentElement = bpmnModel.getFlowElement(currentTask.getTaskDefinitionKey());
            if (currentElement == null) {
                log.warn("在BPMN模型中未找到当前任务节点: {}", currentTask.getTaskDefinitionKey());
                return null;
            }
            
            // 4. 创建节点信息
            NextNodeInfo currentNodeInfo = new NextNodeInfo();
            currentNodeInfo.setNodeId(currentElement.getId());
            currentNodeInfo.setNodeName(currentElement.getName());
            currentNodeInfo.setNodeType(getNodeType(currentElement));
            currentNodeInfo.setDescription(getNodeDescription(currentElement));
            
            // 5. 获取流程版本信息
            WfProcessVersionDto versionInfo = null;
            try {
                ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(currentTask.getProcessDefinitionId())
                    .singleResult();
                
                if (processDefinition != null) {
                    WfProcessVersionQuery versionQuery = new WfProcessVersionQuery();
                    versionQuery.setProcessKey(processDefinition.getKey());
                    List<WfProcessVersionDto> versions = wfProcessVersionManager.selectList(versionQuery);
                    if (!versions.isEmpty()) {
                        versionInfo = versions.get(0);
                    }
                }
            } catch (Exception e) {
                log.warn("获取流程版本信息失败: {}", e.getMessage());
            }
            
            // 6. 从graph_schema中解析节点配置
            if (versionInfo != null && versionInfo.getGraphSchema() != null) {
                try {
                    ObjectMapper objectMapper = new ObjectMapper();
                    Map<String, Object> graphSchema = objectMapper.readValue(versionInfo.getGraphSchema(), Map.class);
                    
                    // 解析节点配置
                    Map<String, Object> nodes = (Map<String, Object>) graphSchema.get("nodes");
                    List<Map<String, Object>> nodesList = (List<Map<String, Object>>) graphSchema.get("nodesList");
                    
                    if (nodes != null || nodesList != null) {
                        // 应用节点配置（包括人员配置和权限配置）
                        applyNodeConfig(currentNodeInfo, nodes, nodesList);
                        log.info("成功应用节点配置: {}", currentNodeInfo.getNodeId());
                    }
                } catch (Exception e) {
                    log.warn("解析graph_schema失败: {}", e.getMessage());
                }
            }
            
            // 7. 设置任务相关信息
            if (currentElement instanceof UserTask) {
                UserTask userTask = (UserTask) currentElement;
                List<NextNodeInfo.HandlerInfo> handlers = getTaskHandlers(userTask);
                currentNodeInfo.setHandlers(handlers);
                currentNodeInfo.setHandlerType("user");
                
                log.info("当前任务节点 {} 的人员配置: {} 个处理人", currentElement.getId(), handlers.size());
            }
            
            return currentNodeInfo;
            
        } catch (Exception e) {
            log.error("获取当前任务节点配置失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 获取模拟的下一步节点数据
     */
    private List<NextNodeInfo> getMockNextNodes() {
        List<NextNodeInfo> nextNodes = new ArrayList<>();
        
        // 模拟用户任务节点
        NextNodeInfo userTask = new NextNodeInfo();
        userTask.setNodeId("task_001");
        userTask.setNodeName("部门经理审批");
        userTask.setNodeType("UserTask");
        userTask.setDescription("用户任务");
        userTask.setHandlerType("user");
        userTask.setIsParallel(false);
        
        // 不再设置handlers，因为前端会从graph_schema获取
        userTask.setHandlers(new ArrayList<>());
        
        nextNodes.add(userTask);
        
        return nextNodes;
    }

    /**
     * 提交审核
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean submitApproval(SubmitApprovalRequest request) {
        log.info("提交审核，任务ID: {}, 流程实例ID: {}, 审批结果: {}", 
                request.getTaskId(), request.getProcessInstanceId(), request.getApprovalResult());
        
        try {
            // 1. 验证任务是否存在且属于当前用户
            Task task = taskService.createTaskQuery()
                    .taskId(request.getTaskId())
                    .singleResult();
            
            if (task == null) {
                log.error("任务不存在，任务ID: {}", request.getTaskId());
                throw new RuntimeException("任务不存在");
            }
            
            String currentUserId = getCurrentUserId();
            log.info("从SecurityUtils获取到当前用户ID: {}", currentUserId);
            
            // 检查任务所有权 - 支持多种分配方式
            boolean hasPermission = false;
            
            // 方式1：直接分配
            if (currentUserId.equals(task.getAssignee())) {
                log.info("任务直接分配给当前用户");
                hasPermission = true;
            }
            
            // 方式2：候选用户和候选组
            if (!hasPermission) {
                List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(request.getTaskId());
                log.info("检查候选用户和候选组，当前用户ID: {}, 候选身份链接数量: {}", currentUserId, identityLinks.size());
                for (IdentityLink link : identityLinks) {
                    log.info("检查身份链接: type={}, userId={}, groupId={}", link.getType(), link.getUserId(), link.getGroupId());
                    if ("candidate".equals(link.getType())) {
                        // 检查候选用户
                        if (link.getUserId() != null && currentUserId.equals(link.getUserId())) {
                            log.info("当前用户是任务的候选用户");
                            hasPermission = true;
                            break;
                        }
                        // 检查候选组
                        if (link.getGroupId() != null) {
                            Set<String> userGroups = getUserGroups(currentUserId);
                            if (userGroups.contains(link.getGroupId())) {
                                log.info("当前用户属于任务的候选组: {}", link.getGroupId());
                                hasPermission = true;
                                break;
                            }
                        }
                    }
                }
            }
            
            if (!hasPermission) {
                log.error("任务不属于当前用户，任务ID: {}, 当前用户: {}, 任务处理人: {}", 
                        request.getTaskId(), currentUserId, task.getAssignee());
                throw new RuntimeException("任务不属于当前用户");
            }
            
            // 2. 根据审批结果处理任务
            String approvalResult = request.getApprovalResult();
            
            if ("PASS".equals(approvalResult)) {
                // 审批通过，完成任务并流转到下一节点
                return handleApprovalPass(request, task);
            } else if ("REJECT".equals(approvalResult)) {
                // 审批拒绝，结束流程
                return handleApprovalReject(request, task);
            } else if ("TRANSFER".equals(approvalResult)) {
                // 转办，将任务转给其他人
                return handleApprovalTransfer(request, task);
            } else {
                log.error("不支持的审批结果: {}", approvalResult);
                throw new RuntimeException("不支持的审批结果: " + approvalResult);
            }
            
        } catch (Exception e) {
            log.error("提交审核失败，任务ID: {}", request.getTaskId(), e);
            throw new RuntimeException("提交审核失败: " + e.getMessage());
        }
    }
    
    /**
     * 处理审批通过
     * 核心逻辑：只设置表单数据，让 Flowable 引擎根据 BPMN 定义自动流转
     */
    private Boolean handleApprovalPass(SubmitApprovalRequest request, Task task) {
        log.info("处理审批通过，任务ID: {}", request.getTaskId());
        
        try {
            // 1. 准备流程变量
            Map<String, Object> variables = new HashMap<>();
            
            // 1.1 设置表单数据到流程变量（关键：让 Flowable 引擎能够评估网关条件）
            Map<String, Object> formData = getFormDataForApproval(request);
            if (formData != null && !formData.isEmpty()) {
                variables.putAll(formData);
                log.info("设置表单数据到流程变量: {}", formData);
            }
            
            // 1.2 设置人员配置（如果有的话，用于后续节点的人员分配）
            List<Map<String, Object>> assigneeConfig = getAssigneeConfigForApproval(request);
            if (assigneeConfig != null && !assigneeConfig.isEmpty()) {
                variables.put("assigneeConfig", assigneeConfig);
                log.info("设置人员配置到流程变量，节点数量: {}", assigneeConfig.size());
            }
            
            // 2. 完成任务，让 Flowable 引擎根据 BPMN 定义和表单数据自动流转
            log.info("准备完成任务，任务ID: {}, 流程变量: {}", request.getTaskId(), variables);
            taskService.complete(request.getTaskId(), variables);
            log.info("任务完成，任务ID: {}", request.getTaskId());
            
            // 3. 检查流程状态并保存审批记录
            checkAndUpdateProcessInstanceStatus(request.getProcessInstanceId());
            saveApprovalRecord(request, task, "APPROVE", "APPROVED");
            
            // 4. 处理抄送和发送通知
            handleCcUsers(request);
            sendNotifications(request, "审批通过");
            
            return true;
            
        } catch (Exception e) {
            log.error("处理审批通过失败，任务ID: {}", request.getTaskId(), e);
            throw new RuntimeException("处理审批通过失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取审批所需的表单数据
     * 优先级：请求中的表单数据 > 流程实例中的表单数据
     */
    private Map<String, Object> getFormDataForApproval(SubmitApprovalRequest request) {
        // 优先使用请求中的表单数据
        Map<String, Object> formData = request.getFormData();
        if (formData != null && !formData.isEmpty()) {
            log.info("使用请求中的表单数据");
            return formData;
        }
        
        // 如果没有，从流程实例中获取
        log.info("请求中没有表单数据，从流程实例中获取");
        formData = getFormDataFromProcessInstance(request.getProcessInstanceId());
        if (formData != null && !formData.isEmpty()) {
            log.info("从流程实例中获取到表单数据: {}", formData);
        } else {
            log.warn("无法获取表单数据");
        }
        
        return formData;
    }
    
    /**
     * 获取审批所需的下一节点人员配置
     * 优先级：请求中的人员配置 > 流程版本中的人员配置
     */
    private List<Map<String, Object>> getAssigneeConfigForApproval(SubmitApprovalRequest request) {
        // 优先使用请求中的人员配置
        List<Map<String, Object>> assigneeConfig = request.getAssigneeConfig();
        if (assigneeConfig != null && !assigneeConfig.isEmpty()) {
            log.info("使用请求中的人员配置，节点数量: {}", assigneeConfig.size());
            return assigneeConfig;
        }
        
        // 如果没有，从流程版本中获取
        log.info("请求中没有人员配置，从流程版本中获取");
        assigneeConfig = getAssigneeConfigFromProcessVersion(request.getProcessInstanceId(), request.getTaskId());
        if (assigneeConfig != null && !assigneeConfig.isEmpty()) {
            log.info("从流程版本中获取到人员配置，节点数量: {}", assigneeConfig.size());
        } else {
            log.warn("无法获取人员配置");
        }
        
        return assigneeConfig;
    }

    /**
     * 处理审批拒绝
     */
    private Boolean handleApprovalReject(SubmitApprovalRequest request, Task task) {
        log.info("处理审批拒绝，任务ID: {}", request.getTaskId());
        
        try {
            // 1. 设置流程变量，标记流程被拒绝
            Map<String, Object> variables = new HashMap<>();
            variables.put("approved", false);
            variables.put("rejectionReason", request.getApprovalOpinion());
            variables.put("rejectedBy", getCurrentUserId());
            variables.put("rejectedAt", LocalDateTime.now());
            
            // 2. 完成任务（流程会结束）
            taskService.complete(request.getTaskId(), variables);
            log.info("任务完成（拒绝），任务ID: {}", request.getTaskId());
            
            // 3. 检查流程实例状态，如果流程还在运行则强制终止
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(request.getProcessInstanceId())
                .singleResult();
            
            if (processInstance != null) {
                log.info("流程实例仍在运行，强制终止流程实例: {}", request.getProcessInstanceId());
                runtimeService.deleteProcessInstance(request.getProcessInstanceId(), "审批被拒绝");
            }
            
            // 4. 更新流程实例状态为已终止
            try {
                wfProcessInstanceService.updateStatusToTerminated(request.getProcessInstanceId(), "审批被拒绝：" + request.getApprovalOpinion());
                log.info("流程实例状态已更新为已终止，流程实例ID: {}", request.getProcessInstanceId());
            } catch (Exception e) {
                log.warn("更新流程实例状态失败，流程实例ID: {}, 错误: {}", request.getProcessInstanceId(), e.getMessage());
                // 不抛出异常，继续执行后续逻辑
            }
            
            // 5. 保存审批记录
            saveApprovalRecord(request, task, "REJECT", "REJECTED");
            
            // 6. 处理抄送
            handleCcUsers(request);
            
            // 7. 发送通知
            sendNotifications(request, "审批拒绝");
            
            return true;
            
        } catch (Exception e) {
            log.error("处理审批拒绝失败，任务ID: {}", request.getTaskId(), e);
            throw new RuntimeException("处理审批拒绝失败: " + e.getMessage());
        }
    }
    
    /**
     * 处理转办
     */
    private Boolean handleApprovalTransfer(SubmitApprovalRequest request, Task task) {
        log.info("处理转办，任务ID: {}", request.getTaskId());
        
        try {
            // 1. 解析转办人员 - 优先从转办人员字段获取
            String transferAssignee = null;
            
            // 尝试从转办人员字段获取
            if (request.getTransferAssignee() != null && !request.getTransferAssignee().trim().isEmpty()) {
                transferAssignee = request.getTransferAssignee().trim();
                log.info("从transferAssignee字段获取转办人员: {}", transferAssignee);
            }
            // 如果转办人员字段为空，尝试从ccUsers字段获取（向后兼容）
            else if (request.getCcUsers() != null && !request.getCcUsers().trim().isEmpty()) {
                String[] transferUsers = request.getCcUsers().split(",");
                if (transferUsers.length > 0) {
                    transferAssignee = transferUsers[0].trim();
                    log.info("从ccUsers字段获取转办人员: {}", transferAssignee);
                }
            }
            
            if (StringUtils.isEmpty(transferAssignee)) {
                throw new RuntimeException("转办人员不能为空");
            }
            
            // 2. 转办任务
            taskService.setAssignee(request.getTaskId(), transferAssignee);
            log.info("任务转办成功，任务ID: {}, 转办给用户: {}", request.getTaskId(), transferAssignee);
            
            // 3. 保存审批记录
            saveApprovalRecord(request, task, "TRANSFER", "TRANSFERRED");
            
            // 4. 发送通知
            sendNotifications(request, "任务转办");
            
            return true;
            
        } catch (Exception e) {
            log.error("处理转办失败，任务ID: {}", request.getTaskId(), e);
            throw new RuntimeException("处理转办失败: " + e.getMessage());
        }
    }
    
    /**
     * 保存审批记录
     */
    private void saveApprovalRecord(SubmitApprovalRequest request, Task task, String approvalType, String approvalResult) {
        try {
            WfProcessApprovalQuery approvalQuery = new WfProcessApprovalQuery();
            approvalQuery.setProcessInstanceId(request.getProcessInstanceId());
            approvalQuery.setTaskId(request.getTaskId());
            approvalQuery.setNodeId(task.getTaskDefinitionKey());
            approvalQuery.setNodeName(task.getName());
            approvalQuery.setApprovalType(approvalType);
            approvalQuery.setApprovalResult(approvalResult);
            approvalQuery.setApprovalOpinion(request.getApprovalOpinion());
            approvalQuery.setApprover(getCurrentUserName());
            approvalQuery.setApproverId(Long.valueOf(getCurrentUserId()));
            approvalQuery.setApprovalTime(LocalDateTime.now());
            
            // 设置新增字段
            // 从下一节点配置中提取下一步处理人
            String nextAssignee = null;
            if (request.getNextNodes() != null && !request.getNextNodes().isEmpty()) {
                // 取第一个节点的第一个处理人作为下一步处理人
                var firstNode = request.getNextNodes().get(0);
                if (firstNode.getHandlers() != null && !firstNode.getHandlers().isEmpty()) {
                    nextAssignee = firstNode.getHandlers().get(0).getId();
                }
            }
            approvalQuery.setNextAssignee(nextAssignee);
            approvalQuery.setCcUsers(request.getCcUsers());
            approvalQuery.setNotifyMethods(request.getNotificationMethods());
            
            // 如果是转办，设置转办人员信息
            if ("TRANSFER".equals(approvalType)) {
                String transferAssignee = request.getTransferAssignee();
                if (StringUtils.isNotEmpty(transferAssignee)) {
                    approvalQuery.setNextAssignee(transferAssignee);
                    log.info("设置转办人员为下一步处理人: {}", transferAssignee);
                }
            }
            
            approvalQuery.setTenantId(1L); // 设置默认租户ID
            
            // 获取流程信息
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                    .processInstanceId(request.getProcessInstanceId())
                    .singleResult();
            
            if (processInstance != null) {
                approvalQuery.setProcessId(Long.valueOf(processInstance.getProcessDefinitionKey().hashCode())); // 使用hashCode作为processId
                approvalQuery.setProcessKey(processInstance.getProcessDefinitionKey());
                approvalQuery.setProcessName(processInstance.getProcessDefinitionName());
            }
            
            boolean result = wfProcessApprovalService.addApprovalRecord(approvalQuery);
            if (!result) {
                log.warn("保存审批记录失败，任务ID: {}", request.getTaskId());
            }
            
        } catch (Exception e) {
            log.error("保存审批记录失败，任务ID: {}", request.getTaskId(), e);
        }
    }
    
    /**
     * 处理抄送用户
     */
    private void handleCcUsers(SubmitApprovalRequest request) {
        try {
            String ccUsers = request.getCcUsers();
            if (StringUtils.isNotEmpty(ccUsers)) {
                String[] ccUserIds = ccUsers.split(",");
                log.info("处理抄送用户: {}", Arrays.toString(ccUserIds));
                
                // TODO: 实现抄送逻辑
                // 1. 保存抄送记录到数据库
                // 2. 发送抄送通知
                
            }
        } catch (Exception e) {
            log.error("处理抄送用户失败", e);
        }
    }
    
    /**
     * 发送通知
     */
    private void sendNotifications(SubmitApprovalRequest request, String action) {
        try {
            String notificationMethods = request.getNotificationMethods();
            if (StringUtils.isNotEmpty(notificationMethods)) {
                String[] methods = notificationMethods.split(",");
                log.info("发送通知，方式: {}, 动作: {}", Arrays.toString(methods), action);
                
                // TODO: 实现通知发送逻辑
                // 1. 系统内部通知
                // 2. 邮件通知
                // 3. 短信通知
                // 4. 微信通知
                
            }
        } catch (Exception e) {
            log.error("发送通知失败", e);
        }
    }
    
    /**
     * 获取当前用户姓名
     */
    private String getCurrentUserName() {
        try {
            // TODO: 从SecurityUtils获取当前用户姓名
            return "当前用户";
        } catch (Exception e) {
            log.warn("无法获取当前用户姓名", e);
            return "未知用户";
        }
    }

    /**
     * 获取设计时的人员配置
     */
    private List<NextNodeInfo.HandlerInfo> getDesignTimeHandlers(String nodeId, WfProcessVersionDto versionInfo) {
        List<NextNodeInfo.HandlerInfo> handlers = new ArrayList<>();
        
        if (versionInfo != null && versionInfo.getAssigneeConfig() != null) {
            try {
                List<Map<String, Object>> assigneeConfig = versionInfo.getAssigneeConfig();
                
                // 查找匹配的节点配置
                for (Map<String, Object> config : assigneeConfig) {
                    String configNodeId = (String) config.get("id");
                    if (nodeId.equals(configNodeId)) {
                        // 处理assignees配置
                        Object assigneesObj = config.get("assignees");
                        if (assigneesObj instanceof List) {
                            List<Map<String, Object>> assigneesList = (List<Map<String, Object>>) assigneesObj;
                            for (Map<String, Object> assignee : assigneesList) {
                                String type = (String) assignee.get("type");
                                Object valueObj = assignee.get("value");
                                
                                if ("user".equals(type) && valueObj instanceof List) {
                                    // 处理用户类型
                                    List<Map<String, Object>> users = (List<Map<String, Object>>) valueObj;
                                    for (Map<String, Object> user : users) {
                                        NextNodeInfo.HandlerInfo handler = new NextNodeInfo.HandlerInfo();
                                        handler.setId(String.valueOf(user.get("id")));
                                        
                                        // 支持多种用户名称字段
                                        String userName = null;
                                        if (user.get("nickName") != null) {
                                            userName = (String) user.get("nickName");
                                        } else if (user.get("userName") != null) {
                                            userName = (String) user.get("userName");
                                        } else if (user.get("name") != null) {
                                            userName = (String) user.get("name");
                                        } else {
                                            userName = String.valueOf(user.get("id")); // 如果没有名称，使用ID
                                        }
                                        handler.setName(userName);
                                        
                                        handler.setType(type);
                                        
                                        // 支持多种账号字段
                                        String account = null;
                                        if (user.get("code") != null) {
                                            account = (String) user.get("code");
                                        } else if (user.get("userName") != null) {
                                            account = (String) user.get("userName");
                                        } else if (user.get("account") != null) {
                                            account = (String) user.get("account");
                                        } else {
                                            account = String.valueOf(user.get("id"));
                                        }
                                        handler.setAccount(account);
                                        
                                        handlers.add(handler);
                                        log.info("添加handler: id={}, name={}, type={}", handler.getId(), handler.getName(), handler.getType());
                                    }
                                } else if ("role".equals(type) && valueObj instanceof List) {
                                    // 处理角色类型
                                    List<Map<String, Object>> roles = (List<Map<String, Object>>) valueObj;
                                    for (Map<String, Object> role : roles) {
                                        NextNodeInfo.HandlerInfo handler = new NextNodeInfo.HandlerInfo();
                                        handler.setId(String.valueOf(role.get("id")));
                                        handler.setName((String) role.get("name"));
                                        handler.setType("role");
                                        handler.setAccount((String) role.get("account"));
                                        handlers.add(handler);
                                    }
                                } else if ("dept".equals(type) && valueObj instanceof List) {
                                    // 处理部门类型
                                    List<Map<String, Object>> depts = (List<Map<String, Object>>) valueObj;
                                    for (Map<String, Object> dept : depts) {
                                        NextNodeInfo.HandlerInfo handler = new NextNodeInfo.HandlerInfo();
                                        handler.setId(String.valueOf(dept.get("id")));
                                        handler.setName((String) dept.get("name"));
                                        handler.setType("dept");
                                        handler.setAccount((String) dept.get("account"));
                                        handlers.add(handler);
                                    }
                                } else if ("post".equals(type) && valueObj instanceof List) {
                                    // 处理岗位类型
                                    List<Map<String, Object>> posts = (List<Map<String, Object>>) valueObj;
                                    for (Map<String, Object> post : posts) {
                                        NextNodeInfo.HandlerInfo handler = new NextNodeInfo.HandlerInfo();
                                        handler.setId(String.valueOf(post.get("id")));
                                        handler.setName((String) post.get("name"));
                                        handler.setType("post");
                                        handler.setAccount((String) post.get("account"));
                                        handlers.add(handler);
                                    }
                                } else if ("starter".equals(type) || "starterDeptLeader".equals(type) || "starterDeptParentLeader".equals(type)) {
                                    // 处理表达式类型
                                    NextNodeInfo.HandlerInfo handler = new NextNodeInfo.HandlerInfo();
                                    handler.setId(type);
                                    handler.setName(getExpressionText(type));
                                    handler.setType("expression");
                                    handler.setAccount(type);
                                    handlers.add(handler);
                                }
                            }
                        }
                        break;
                    }
                }
            } catch (Exception e) {
                log.warn("解析设计时人员配置失败", e);
            }
        }
        
        return handlers;
    }
    
    /**
     * 合并人员配置
     */
    private List<NextNodeInfo.HandlerInfo> mergeHandlers(List<NextNodeInfo.HandlerInfo> bpmnHandlers, List<NextNodeInfo.HandlerInfo> designHandlers) {
        List<NextNodeInfo.HandlerInfo> mergedHandlers = new ArrayList<>();
        Set<String> addedIds = new HashSet<>();
        
        // 优先添加设计时的人员配置
        if (designHandlers != null) {
            for (NextNodeInfo.HandlerInfo handler : designHandlers) {
                if (!addedIds.contains(handler.getId())) {
                    mergedHandlers.add(handler);
                    addedIds.add(handler.getId());
                }
            }
        }
        
        // 添加BPMN中的人员配置（如果设计时没有配置）
        if (bpmnHandlers != null) {
            for (NextNodeInfo.HandlerInfo handler : bpmnHandlers) {
                if (!addedIds.contains(handler.getId())) {
                    mergedHandlers.add(handler);
                    addedIds.add(handler.getId());
                }
            }
        }
        
        return mergedHandlers;
    }
    
    /**
     * 从graph_schema中应用人员配置到节点
     */
    @SuppressWarnings("unchecked")
    private void applyAssigneeConfigFromGraphSchema(List<NextNodeInfo> nextNodes, Map<String, Object> graphSchema) {
        try {
            if (graphSchema == null) {
                return;
            }
            
            log.info("开始解析graph_schema，结构: {}", graphSchema.keySet());
            
            // 支持两种数据结构：nodes对象和nodes数组
            Object nodesObj = graphSchema.get("nodes");
            Map<String, Object> nodes = null;
            List<Map<String, Object>> nodesList = null;
            
            if (nodesObj instanceof Map) {
                nodes = (Map<String, Object>) nodesObj;
                log.info("使用nodes对象格式，节点数量: {}", nodes.size());
            } else if (nodesObj instanceof List) {
                nodesList = (List<Map<String, Object>>) nodesObj;
                log.info("使用nodes数组格式，节点数量: {}", nodesList.size());
            }
            
            if (nodes == null && nodesList == null) {
                log.warn("graph_schema中没有找到nodes字段");
                return;
            }
            
            // 遍历下一节点，查找对应的graph_schema节点配置
            for (NextNodeInfo nextNode : nextNodes) {
                String nodeId = nextNode.getNodeId();
                log.info("处理节点: {}", nodeId);
                
                // 处理普通节点
                applyNodeConfig(nextNode, nodes, nodesList);
                
                // 处理网关分支节点
                if (nextNode.getGatewayBranches() != null && !nextNode.getGatewayBranches().isEmpty()) {
                    log.info("处理网关节点 {} 的分支，分支数量: {}", nodeId, nextNode.getGatewayBranches().size());
                    
                    for (GatewayBranchInfo branch : nextNode.getGatewayBranches()) {
                        if (branch.getTargetNodeInfo() != null) {
                            log.info("处理网关分支目标节点: {}", branch.getTargetNodeId());
                            applyNodeConfig(branch.getTargetNodeInfo(), nodes, nodesList);
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("应用graph_schema配置失败", e);
        }
    }
    
    /**
     * 应用节点配置
     */
    @SuppressWarnings("unchecked")
    private void applyNodeConfig(NextNodeInfo nextNode, Map<String, Object> nodes, List<Map<String, Object>> nodesList) {
        String nodeId = nextNode.getNodeId();
        log.info("应用节点配置: {}", nodeId);
        
        Map<String, Object> nodeConfig = null;
        
        // 从nodes对象中查找
        if (nodes != null) {
            Object nodeData = nodes.get(nodeId);
            if (nodeData instanceof Map) {
                nodeConfig = (Map<String, Object>) nodeData;
                log.info("从nodes对象中找到节点配置: {}", nodeConfig.keySet());
            }
        }
        
        // 从nodes数组中查找
        if (nodeConfig == null && nodesList != null) {
            for (Map<String, Object> node : nodesList) {
                String id = (String) node.get("id");
                if (nodeId.equals(id)) {
                    nodeConfig = node;
                    log.info("从nodes数组中找到节点配置: {}", nodeConfig.keySet());
                    break;
                }
            }
        }
        
        if (nodeConfig != null) {
            // 从data字段中获取assignees配置
            Object dataObj = nodeConfig.get("data");
            if (dataObj instanceof Map) {
                Map<String, Object> data = (Map<String, Object>) dataObj;
                log.info("节点data字段内容: {}", data.keySet());
                
                Object assigneesObj = data.get("assignees");
                if (assigneesObj instanceof List) {
                    List<Map<String, Object>> assignees = (List<Map<String, Object>>) assigneesObj;
                    log.info("找到assignees配置，数量: {}", assignees.size());
                    
                    // 转换assignees为HandlerInfo格式
                    List<NextNodeInfo.HandlerInfo> handlers = new ArrayList<>();
                    
                    for (Map<String, Object> assignee : assignees) {
                        String type = (String) assignee.get("type");
                        Object valueObj = assignee.get("value");
                        
                        log.info("处理assignee: type={}, value={}", type, valueObj);
                        
                        if (valueObj instanceof List) {
                            List<Map<String, Object>> values = (List<Map<String, Object>>) valueObj;
                            for (Map<String, Object> value : values) {
                                NextNodeInfo.HandlerInfo handler = new NextNodeInfo.HandlerInfo();
                                handler.setId(String.valueOf(value.get("id")));
                                
                                // 支持多种用户名称字段
                                String userName = null;
                                if (value.get("nickName") != null) {
                                    userName = (String) value.get("nickName");
                                } else if (value.get("userName") != null) {
                                    userName = (String) value.get("userName");
                                } else if (value.get("name") != null) {
                                    userName = (String) value.get("name");
                                } else {
                                    userName = String.valueOf(value.get("id")); // 如果没有名称，使用ID
                                }
                                handler.setName(userName);
                                
                                handler.setType(type);
                                
                                // 支持多种账号字段
                                String account = null;
                                if (value.get("code") != null) {
                                    account = (String) value.get("code");
                                } else if (value.get("userName") != null) {
                                    account = (String) value.get("userName");
                                } else if (value.get("account") != null) {
                                    account = (String) value.get("account");
                                } else {
                                    account = String.valueOf(value.get("id"));
                                }
                                handler.setAccount(account);
                                
                                handlers.add(handler);
                                log.info("添加handler: id={}, name={}, type={}", handler.getId(), handler.getName(), handler.getType());
                            }
                        } else if (type != null) {
                            // 处理表达式类型的人员配置（如starter、starterDeptLeader等）
                            NextNodeInfo.HandlerInfo handler = new NextNodeInfo.HandlerInfo();
                            handler.setId(type);
                            handler.setName(getExpressionText(type));
                            handler.setType(type);
                            handler.setAccount(type);
                            handlers.add(handler);
                            log.info("添加表达式handler: id={}, name={}, type={}", handler.getId(), handler.getName(), handler.getType());
                        }
                    }
                    
                    nextNode.setHandlers(handlers);
                    log.info("节点 {} 应用了 {} 个人员配置", nodeId, handlers.size());
                } else {
                    log.info("节点 {} 的data中没有assignees配置或格式不正确", nodeId);
                }
                
                // 处理抄送配置
                Object ccUsersObj = data.get("cc");
                if (ccUsersObj instanceof List) {
                    List<Map<String, Object>> ccUsers = (List<Map<String, Object>>) ccUsersObj;
                    log.info("找到cc配置，数量: {}", ccUsers.size());
                    
                    // 转换ccUsers为HandlerInfo格式
                    List<NextNodeInfo.HandlerInfo> ccUsersList = new ArrayList<>();
                    
                    for (Map<String, Object> ccUser : ccUsers) {
                        String type = (String) ccUser.get("type");
                        Object valueObj = ccUser.get("value");
                        
                        log.info("处理ccUser: type={}, value={}", type, valueObj);
                        
                        if (valueObj instanceof List) {
                            List<Map<String, Object>> values = (List<Map<String, Object>>) valueObj;
                            for (Map<String, Object> value : values) {
                                NextNodeInfo.HandlerInfo handler = new NextNodeInfo.HandlerInfo();
                                handler.setId(String.valueOf(value.get("id")));
                                // 支持多种用户名称字段
                                String userName = null;
                                if (value.get("nickName") != null) {
                                    userName = (String) value.get("nickName");
                                } else if (value.get("userName") != null) {
                                    userName = (String) value.get("userName");
                                } else if (value.get("name") != null) {
                                    userName = (String) value.get("name");
                                } else {
                                    userName = String.valueOf(value.get("id")); // 如果没有名称，使用ID
                                }
                                handler.setName(userName);
                                handler.setType(type);
                                // 支持多种账号字段
                                String account = null;
                                if (value.get("code") != null) {
                                    account = (String) value.get("code");
                                } else if (value.get("userName") != null) {
                                    account = (String) value.get("userName");
                                } else if (value.get("account") != null) {
                                    account = (String) value.get("account");
                                } else {
                                    account = String.valueOf(value.get("id"));
                                }
                                handler.setAccount(account);
                                ccUsersList.add(handler);
                                log.info("添加ccUser: id={}, name={}, type={}", handler.getId(), handler.getName(), handler.getType());
                            }
                        } else if (type != null) {
                            // 处理表达式类型的抄送配置
                            NextNodeInfo.HandlerInfo handler = new NextNodeInfo.HandlerInfo();
                            handler.setId(type);
                            handler.setName(getExpressionText(type));
                            handler.setType(type);
                            handler.setAccount(type);
                            ccUsersList.add(handler);
                            log.info("添加表达式ccUser: id={}, name={}, type={}", handler.getId(), handler.getName(), handler.getType());
                        }
                    }
                    
                    nextNode.setCcUsers(ccUsersList);
                    log.info("节点 {} 应用了 {} 个抄送配置", nodeId, ccUsersList.size());
                } else {
                    log.info("节点 {} 的data中没有cc配置或格式不正确", nodeId);
                }
                
                // 处理通知方式配置
                Object notificationMethodsObj = data.get("notifyMethods");
                if (notificationMethodsObj instanceof String) {
                    String notificationMethods = (String) notificationMethodsObj;
                    nextNode.setNotificationMethods(notificationMethods);
                    log.info("节点 {} 应用了通知方式配置: {}", nodeId, notificationMethods);
                } else {
                    log.info("节点 {} 的data中没有notifyMethods配置或格式不正确", nodeId);
                }
                
                // 处理高级配置（包括人员编辑权限等）
                Object advancedObj = data.get("advanced");
                if (advancedObj instanceof Map) {
                    Map<String, Object> advanced = (Map<String, Object>) advancedObj;
                    log.info("节点 {} 的高级配置: {}", nodeId, advanced.keySet());
                    
                    // 将高级配置设置到节点的通用配置中
                    Map<String, Object> generalNodeConfig = new HashMap<>();
                    generalNodeConfig.put("advanced", advanced);
                    nextNode.setNodeConfig(generalNodeConfig);
                    
                    log.info("节点 {} 应用了高级配置", nodeId);
                }
            } else {
                log.info("节点 {} 的配置中没有data字段", nodeId);
            }
        } else {
            log.info("未找到节点 {} 的graph_schema配置", nodeId);
        }
    }

    /**
     * 获取表达式文本
     */
    private String getExpressionText(String type) {
        switch (type) {
            case "starter":
                return "流程发起人";
            case "starterDeptLeader":
                return "发起人部门负责人";
            case "starterDeptParentLeader":
                return "发起人上级部门负责人";
            default:
                return type;
        }
    }
    
    /**
     * 检查流程实例是否已完成，如果已完成则更新业务表状态
     */
    private void checkAndUpdateProcessInstanceStatus(String processInstanceId) {
        try {
            log.info("检查流程实例 {} 是否已完成", processInstanceId);
            
            // 查询流程实例是否还在运行
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();
            
            if (processInstance == null) {
                // 流程实例不存在，说明流程已完成
                log.info("流程实例 {} 已完成，开始更新业务表状态", processInstanceId);
                
                // 更新 wf_process_instance 表状态为 COMPLETED
                updateProcessInstanceStatusToCompleted(processInstanceId);
                
            } else {
                log.info("流程实例 {} 仍在运行中", processInstanceId);
            }
            
        } catch (Exception e) {
            log.error("检查流程实例状态失败，processInstanceId: {}", processInstanceId, e);
        }
    }
    
    /**
     * 更新流程实例状态为已完成
     */
    private void updateProcessInstanceStatusToCompleted(String processInstanceId) {
        try {
            log.info("流程实例 {} 已完成，开始发布流程状态变更事件", processInstanceId);
            
            // 获取流程实例信息
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();
            
            if (processInstance != null) {
                // 发布流程状态变更事件
                processStatusManager.publishStatusChangedEvent(
                    this, 
                    processInstanceId, 
                    processInstance.getBusinessKey(), 
                    processInstance.getProcessDefinitionKey(),
                    "RUNNING", // 假设之前是运行中状态
                    "COMPLETED",
                    "流程正常完成"
                );
                
                log.info("流程状态变更事件发布成功，processInstanceId: {}", processInstanceId);
                
            } else {
                // 流程实例不存在，说明已经完成，发布事件时使用默认值
                processStatusManager.publishStatusChangedEvent(
                    this, 
                    processInstanceId, 
                    null, 
                    null,
                    "RUNNING", // 假设之前是运行中状态
                    "COMPLETED",
                    "流程正常完成"
                );
                
                log.info("流程状态变更事件发布成功（使用默认值），processInstanceId: {}", processInstanceId);
            }
            
        } catch (Exception e) {
            log.error("发布流程状态变更事件失败，processInstanceId: {}", processInstanceId, e);
        }
    }

    /**
     * 从流程实例中获取表单数据
     */
    private Map<String, Object> getFormDataFromProcessInstance(String processInstanceId) {
        try {
            // 从流程实例变量中获取表单数据
            Map<String, Object> variables = runtimeService.getVariables(processInstanceId);
            
            // 查找表单数据
            Object formDataObj = variables.get("formData");
            if (formDataObj instanceof Map) {
                @SuppressWarnings("unchecked")
                Map<String, Object> formData = (Map<String, Object>) formDataObj;
                log.info("从流程实例变量中获取到表单数据: {}", formData);
                return formData;
            }
            
            // 如果没有找到 formData，尝试从其他可能的字段中获取
            for (Map.Entry<String, Object> entry : variables.entrySet()) {
                String key = entry.getKey();
                Object value = entry.getValue();
                
                // 跳过系统字段和 assigneeConfig
                if ("assigneeConfig".equals(key) || "approved".equals(key) || "rejectionReason".equals(key) || 
                    "rejectedBy".equals(key) || "rejectedAt".equals(key)) {
                    continue;
                }
                
                // 如果值是 Map 类型，可能是表单数据
                if (value instanceof Map) {
                    @SuppressWarnings("unchecked")
                    Map<String, Object> potentialFormData = (Map<String, Object>) value;
                    // 检查是否包含表单字段（简单的判断逻辑）
                    if (potentialFormData.size() > 0 && !potentialFormData.containsKey("id")) {
                        log.info("从流程实例变量中推断出表单数据: {}", potentialFormData);
                        return potentialFormData;
                    }
                }
            }
            
            log.warn("无法从流程实例变量中找到表单数据");
            return null;
            
        } catch (Exception e) {
            log.error("从流程实例中获取表单数据失败: {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 从流程版本中获取下一节点的人员配置
     * 核心逻辑：
     * 1. 获取流程实例和流程定义信息
     * 2. 查询流程版本中的人员配置
     * 3. 根据当前任务预测下一节点配置
     */
    private List<Map<String, Object>> getAssigneeConfigFromProcessVersion(String processInstanceId, String currentTaskId) {
        try {
            // 1. 获取流程实例信息
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();
            
            if (processInstance == null) {
                log.warn("流程实例不存在: {}", processInstanceId);
                return null;
            }
            
            // 2. 获取流程定义信息
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(processInstance.getProcessDefinitionId())
                .singleResult();
            
            if (processDefinition == null) {
                log.warn("流程定义不存在: {}", processInstance.getProcessDefinitionId());
                return null;
            }
            
            // 3. 从流程定义中获取流程ID
            String processId = processDefinition.getKey();
            log.info("从流程定义中获取到流程ID: {}", processId);
            
            // 4. 查询流程版本信息
            Integer latestVersion = wfProcessVersionService.getLatestVersion(processId);
            if (latestVersion == null) {
                log.warn("无法获取流程最新版本号，流程ID: {}", processId);
                return null;
            }
            
            WfProcessVersionDto versionInfo = wfProcessVersionService.getProcessVersion(processId, latestVersion);
            if (versionInfo == null) {
                log.warn("流程版本信息不存在，流程ID: {}, 版本: {}", processId, latestVersion);
                return null;
            }
            
            // 5. 获取流程版本中的人员配置
            List<Map<String, Object>> allAssigneeConfig = versionInfo.getAssigneeConfig();
            if (allAssigneeConfig == null || allAssigneeConfig.isEmpty()) {
                log.warn("流程版本中的人员配置为空，流程ID: {}", processId);
                return null;
            }
            
            // 6. 根据当前任务预测下一节点配置
            List<Map<String, Object>> nextNodeConfig = predictNextNodeAssigneeConfig(currentTaskId, allAssigneeConfig);
            if (nextNodeConfig != null && !nextNodeConfig.isEmpty()) {
                log.info("预测到下一节点的人员配置，节点数量: {}", nextNodeConfig.size());
                return nextNodeConfig;
            }
            
            // 7. 如果无法预测，返回所有配置（兼容性处理）
            log.warn("无法预测下一节点，返回所有人员配置");
            return allAssigneeConfig;
            
        } catch (Exception e) {
            log.error("从流程版本中获取人员配置失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 预测下一节点的人员配置
     * 核心逻辑：
     * 1. 优先使用 BPMN 模型动态获取下一节点
     * 2. 如果失败，使用静态配置预测（备用方案）
     */
    private List<Map<String, Object>> predictNextNodeAssigneeConfig(String currentTaskId, List<Map<String, Object>> allAssigneeConfig) {
        try {
            // 方法1：使用 Flowable 的 BPMN 模型来动态获取下一节点
            List<Map<String, Object>> nextNodeConfig = getNextNodeConfigFromBpmn(currentTaskId);
            if (nextNodeConfig != null && !nextNodeConfig.isEmpty()) {
                log.info("通过 BPMN 模型获取到下一节点配置，节点数量: {}", nextNodeConfig.size());
                return nextNodeConfig;
            }
            
            // 方法2：基于流程版本的静态配置预测（备用方案）
            log.info("BPMN 模型获取失败，使用静态配置预测");
            return predictNextNodeFromStaticConfig(currentTaskId, allAssigneeConfig);
            
        } catch (Exception e) {
            log.error("预测下一节点人员配置失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 通过 BPMN 模型获取下一节点配置
     * 核心逻辑：
     * 1. 获取当前任务和 BPMN 模型
     * 2. 递归遍历所有可能的后续节点
     * 3. 收集用户任务节点的人员配置
     */
    private List<Map<String, Object>> getNextNodeConfigFromBpmn(String currentTaskId) {
        try {
            // 1. 获取当前任务
            Task currentTask = taskService.createTaskQuery()
                .taskId(currentTaskId)
                .singleResult();
            
            if (currentTask == null) {
                log.warn("当前任务不存在: {}", currentTaskId);
                return null;
            }
            
            // 2. 获取流程定义的 BPMN 模型
            BpmnModel bpmnModel = repositoryService.getBpmnModel(currentTask.getProcessDefinitionId());
            if (bpmnModel == null) {
                log.warn("无法获取 BPMN 模型，流程定义ID: {}", currentTask.getProcessDefinitionId());
                return null;
            }
            
            // 3. 获取当前任务节点
            FlowElement currentElement = bpmnModel.getFlowElement(currentTask.getTaskDefinitionKey());
            if (currentElement == null) {
                log.warn("在 BPMN 模型中未找到当前任务节点: {}", currentTask.getTaskDefinitionKey());
                return null;
            }
            
            // 4. 递归获取所有后续节点，直到找到用户任务节点
            List<Map<String, Object>> nextNodes = new ArrayList<>();
            Set<String> visitedNodes = new HashSet<>();
            collectNextUserTasks(currentElement, bpmnModel, nextNodes, visitedNodes);
            
            if (!nextNodes.isEmpty()) {
                log.info("通过 BPMN 模型获取到 {} 个后续用户任务节点", nextNodes.size());
                return nextNodes;
            }
            
            return null;
            
        } catch (Exception e) {
            log.error("通过 BPMN 模型获取下一节点配置失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 递归收集后续的用户任务节点
     * 核心逻辑：
     * 1. 遍历当前节点的所有出线
     * 2. 如果是用户任务，收集人员配置信息
     * 3. 如果是网关或其他节点，继续递归遍历
     * 4. 使用 visitedNodes 避免循环遍历
     */
    private void collectNextUserTasks(FlowElement currentElement, BpmnModel bpmnModel, 
                                    List<Map<String, Object>> nextNodes, Set<String> visitedNodes) {
        // 避免循环遍历
        if (currentElement == null || visitedNodes.contains(currentElement.getId())) {
            return;
        }
        
        visitedNodes.add(currentElement.getId());
        
        if (currentElement instanceof FlowNode) {
            FlowNode flowNode = (FlowNode) currentElement;
            List<SequenceFlow> outgoingFlows = flowNode.getOutgoingFlows();
            
            if (outgoingFlows != null && !outgoingFlows.isEmpty()) {
                for (SequenceFlow flow : outgoingFlows) {
                    FlowElement targetElement = flow.getTargetFlowElement();
                    if (targetElement != null) {
                        
                        // 如果是用户任务，添加到结果中
                        if (targetElement instanceof UserTask) {
                            Map<String, Object> nextNode = createUserTaskConfig(targetElement);
                            nextNodes.add(nextNode);
                            log.info("找到用户任务节点: {}", nextNode.get("name"));
                        }
                        // 如果是网关，继续递归遍历所有可能的路径
                        else if (targetElement instanceof Gateway) {
                            log.info("遇到网关节点: {}, 继续遍历所有可能的路径", targetElement.getId());
                            
                            // 记录网关连线的条件表达式（用于调试）
                            logGatewayFlowConditions(targetElement);
                            
                            collectNextUserTasks(targetElement, bpmnModel, nextNodes, visitedNodes);
                        }
                        // 如果是其他类型的节点，也继续遍历
                        else {
                            log.info("遇到其他类型节点: {} ({}), 继续遍历", targetElement.getId(), targetElement.getClass().getSimpleName());
                            collectNextUserTasks(targetElement, bpmnModel, nextNodes, visitedNodes);
                        }
                    }
                }
            }
        }
    }
    
    /**
     * 创建用户任务节点配置
     */
    private Map<String, Object> createUserTaskConfig(FlowElement targetElement) {
        Map<String, Object> nextNode = new HashMap<>();
        nextNode.put("id", targetElement.getId());
        nextNode.put("name", targetElement.getName());
        nextNode.put("type", targetElement.getClass().getSimpleName());
        
        // 获取用户任务的人员配置信息
        if (targetElement instanceof UserTask) {
            UserTask userTask = (UserTask) targetElement;
            Map<String, Object> assigneeInfo = new HashMap<>();
            
            // 获取 assignee（直接负责人）
            if (userTask.getAssignee() != null) {
                assigneeInfo.put("assignee", userTask.getAssignee());
            }
            
            // 获取候选用户
            if (userTask.getCandidateUsers() != null && !userTask.getCandidateUsers().isEmpty()) {
                assigneeInfo.put("candidateUsers", userTask.getCandidateUsers());
            }
            
            // 获取候选组
            if (userTask.getCandidateGroups() != null && !userTask.getCandidateGroups().isEmpty()) {
                assigneeInfo.put("candidateGroups", userTask.getCandidateGroups());
            }
            
            nextNode.put("assigneeInfo", assigneeInfo);
        }
        
        return nextNode;
    }
    
    /**
     * 记录网关连线的条件表达式（用于调试）
     */
    private void logGatewayFlowConditions(FlowElement gatewayElement) {
        if (gatewayElement instanceof FlowNode) {
            FlowNode flowNode = (FlowNode) gatewayElement;
            List<SequenceFlow> gatewayOutgoingFlows = flowNode.getOutgoingFlows();
            
            if (gatewayOutgoingFlows != null && !gatewayOutgoingFlows.isEmpty()) {
                for (SequenceFlow gatewayFlow : gatewayOutgoingFlows) {
                    String conditionExpression = gatewayFlow.getConditionExpression();
                    if (conditionExpression != null && !conditionExpression.trim().isEmpty()) {
                        log.info("网关连线 {} -> {} 的条件表达式: {}", 
                            gatewayFlow.getId(), gatewayFlow.getTargetFlowElement().getId(), conditionExpression);
                    } else {
                        log.info("网关连线 {} -> {} 没有条件表达式", 
                            gatewayFlow.getId(), gatewayFlow.getTargetFlowElement().getId());
                    }
                }
            }
        }
    }
    
    /**
     * 基于流程版本的静态配置预测下一节点（备用方案）
     */
    private List<Map<String, Object>> predictNextNodeFromStaticConfig(String currentTaskId, List<Map<String, Object>> allAssigneeConfig) {
        try {
            // 根据当前任务ID，在流程版本中找到对应的节点配置
            Map<String, Object> currentNodeConfig = null;
            for (Map<String, Object> config : allAssigneeConfig) {
                String nodeId = (String) config.get("id");
                if (currentTaskId.equals(nodeId)) {
                    currentNodeConfig = config;
                    break;
                }
            }
            
            if (currentNodeConfig == null) {
                log.warn("在流程版本中未找到当前任务节点配置: {}", currentTaskId);
                return null;
            }
            
            // 获取当前节点在流程版本中的位置
            int currentIndex = -1;
            for (int i = 0; i < allAssigneeConfig.size(); i++) {
                if (allAssigneeConfig.get(i) == currentNodeConfig) {
                    currentIndex = i;
                    break;
                }
            }
            
            if (currentIndex == -1) {
                log.warn("无法确定当前节点在流程版本中的位置: {}", currentTaskId);
                return null;
            }
            
            // 获取下一节点配置（如果存在）
            if (currentIndex + 1 < allAssigneeConfig.size()) {
                Map<String, Object> nextNodeConfig = allAssigneeConfig.get(currentIndex + 1);
                log.info("通过静态配置找到下一节点配置: {}", nextNodeConfig);
                return List.of(nextNodeConfig);
            }
            
            log.info("当前节点是最后一个节点，没有下一节点");
            return null;
            
        } catch (Exception e) {
            log.error("基于静态配置预测下一节点失败: {}", e.getMessage(), e);
            return null;
        }
    }
}
